<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  
  <title>Hexo</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta property="og:type" content="website">
<meta property="og:title" content="Hexo">
<meta property="og:url" content="https://goofyer.gitee.io/notes-on-computer-expertise/page/8/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:locale" content="en_US">
<meta property="article:author" content="John Doe">
<meta name="twitter:card" content="summary">
  
    <link rel="alternate" href="/notes-on-computer-expertise/atom.xml" title="Hexo" type="application/atom+xml">
  
  
    <link rel="shortcut icon" href="/notes-on-computer-expertise/favicon.png">
  
  
    
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/typeface-source-code-pro@0.0.71/index.min.css">

  
  
<link rel="stylesheet" href="/notes-on-computer-expertise/css/style.css">

  
    
<link rel="stylesheet" href="/notes-on-computer-expertise/fancybox/jquery.fancybox.min.css">

  
<meta name="generator" content="Hexo 5.4.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/notes-on-computer-expertise/" id="logo">Hexo</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/notes-on-computer-expertise/">Home</a>
        
          <a class="main-nav-link" href="/notes-on-computer-expertise/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/notes-on-computer-expertise/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="https://goofyer.gitee.io/notes-on-computer-expertise"></form>
      </div>
    </div>
  </div>
</header>

      <div class="outer">
        <section id="main">
  
    <article id="post-Java/第二十九章Maven基础" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E4%B9%9D%E7%AB%A0Maven%E5%9F%BA%E7%A1%80/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:37:21.219Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="第二十九章Maven基础"><a href="#第二十九章Maven基础" class="headerlink" title="第二十九章Maven基础"></a>第二十九章Maven基础</h2><h3 id="第1节-Maven基本概念"><a href="#第1节-Maven基本概念" class="headerlink" title="第1节 Maven基本概念"></a>第1节 Maven基本概念</h3><ul>
<li><p>maven概述</p>
<ul>
<li><p>什么是Maven？</p>
<ul>
<li>Maven 的正确发音是[ˈmevən]，而不是“马瘟”以及其他什么瘟。Maven 在美国是一个口语化的词语，代表专家、内行的意思。</li>
<li>一个对 Maven 比较正式的定义是这么说的：Maven 是一个项目管理工具，它包含了一个项目对象模型 (POM：Project Object Model)，一组标准集合，一个项目生命周期(Project Lifecycle)，一个依赖管 理系统(Dependency Management System)和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。</li>
</ul>
</li>
<li><p>Maven能解决什么问题？</p>
<ul>
<li><p>可以用更通俗的方式来说明。我们知道，项目开发不仅仅是写写代码而已，期间会伴随着各种必不可少的事情要做，下面列举几个感受一下：</p>
<ul>
<li>1、我们需要引用各种 jar 包，尤其是比较大的工程，引用的 jar 包往往有几十个乃至上百个， 每用到一种 jar 包，都需要手动引入工程目录，而且经常遇到各种让人抓狂的 jar 包冲突，版本冲突。</li>
<li>2、我们辛辛苦苦写好了 Java 文件，可是只懂 0 和 1 的白痴电脑却完全读不懂，需要将它编译成二进制字节码。好歹现在这项工作可以由各种集成开发工具帮我们完成，Eclipse、IDEA 等都可以将代码即时编译。当然，如果你嫌生命漫长，何不铺张，也可以用记事本来敲代码，然后用 javac 命令一个个地去编译，逗电脑玩。</li>
<li>3、世界上没有不存在 bug 的代码，计算机喜欢 bug 就和人们总是喜欢美女帅哥一样。为了追求美为了减少 bug，因此写完了代码，我们还要写一些单元测试，然后一个个的运行来检验代码质量。</li>
<li>4、再优雅的代码也是要出来卖的。我们后面还需要把代码与各种配置文件、资源整合到一起，定型打包，如果是 web 项目，还需要将之发布到服务器，供人蹂躏。试想，如果现在有一种工具，可以把你从上面的繁琐工作中解放出来，能帮你构建工程，管理 jar 包，编译代码，还能帮你自动运行单元测试，打包，生成报表，甚至能帮你部署项目，生成 Web 站 点，你会心动吗？Maven 就可以解决上面所提到的这些问题。</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>maven依赖管理的概念</p>
</li>
<li><p>Maven的优势举例</p>
<ul>
<li>前面我们通过 Web 阶段项目，要能够将项目运行起来，就必须将该项目所依赖的一些 jar 包添加到 工程中，否则项目就不能运行。试想如果具有相同架构的项目有十个，那么我们就需要将这一份 jar 包复制到十个不同的工程中。我们一起来看一个 CRM项目的工程大小。 使用传统 Web 项目构建的 CRM 项目如下：</li>
<li>原因主要是因为上面的 WEB 程序要运行，我们必须将项目运行所需的 Jar 包复制到工程目录中，从 而导致了工程很大。</li>
<li>同样的项目，如果我们使用 Maven 工程来构建，会发现总体上工程的大小会少很多。</li>
</ul>
</li>
<li><p>1.2.2项目的一件构建</p>
</li>
</ul>
<h3 id="第2节-Maven的安装和仓库种类"><a href="#第2节-Maven的安装和仓库种类" class="headerlink" title="第2节 Maven的安装和仓库种类"></a>第2节 Maven的安装和仓库种类</h3><ul>
<li>Maven环境变量配置</li>
<li>仓库的种类和彼此关系</li>
</ul>
<h3 id="第3节-Maven标准目录结构和常用命令"><a href="#第3节-Maven标准目录结构和常用命令" class="headerlink" title="第3节 Maven标准目录结构和常用命令"></a>第3节 Maven标准目录结构和常用命令</h3><ul>
<li>maven标准目录结构</li>
<li><p>maven常用命令</p>
<ul>
<li><p>1、mvn clean：删除编译好的项目信息</p>
<ul>
<li>mvn clean：删除编译好的项目信息。进入公司后，接别人的项目进行开发，删除别人在本地编译好的所有信息。每个人的开发环境不一定相同，在别人电脑上编译好的代码 在自己电脑上不一定运行的通。</li>
</ul>
</li>
<li><p>2、mvn compile：编译项目</p>
<ul>
<li>mvn compile：编译项目。将src中main下的代码进行编译，放置在target目录下。</li>
</ul>
</li>
<li><p>3、mvn test</p>
</li>
<li>4、mvn package</li>
<li><p>5、mvn install</p>
<ul>
<li>mvn install：执行mvn compile、mvn test、mvn package所做的工作。</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="第4节-Maven生命周期和概念模型图"><a href="#第4节-Maven生命周期和概念模型图" class="headerlink" title="第4节 Maven生命周期和概念模型图"></a>第4节 Maven生命周期和概念模型图</h3><ul>
<li>maven生命周期</li>
<li>maven概念模型图</li>
<li><p>整个项目中，pom.xml文件 共有3类信息：</p>
<ul>
<li>项目自身信息</li>
<li>项目运行所依赖的jar包信息</li>
<li>运行环境信息（jdk、Tomcat）</li>
</ul>
</li>
</ul>
<h3 id="第5节-使用骨架创建Maven的Java工程"><a href="#第5节-使用骨架创建Maven的Java工程" class="headerlink" title="第5节 使用骨架创建Maven的Java工程"></a>第5节 使用骨架创建Maven的Java工程</h3><ul>
<li>idea集成maven插件</li>
</ul>
<h3 id="第6节-Maven工程Servlet实例"><a href="#第6节-Maven工程Servlet实例" class="headerlink" title="第6节 Maven工程Servlet实例"></a>第6节 Maven工程Servlet实例</h3><ul>
<li><p>maven工程servlet实例之指定web</p>
<ul>
<li>简单的使用servlet跳转的maven的web工程，servlet直接跳转到jsp页面。</li>
<li>想要让java文件夹下，可以写jsp页面</li>
</ul>
</li>
<li><p>package com.itheima.dao;<br>ItemsDao.java<br>package com.itheima.dao;</p>
</li>
</ul>
<p>import com.itheima.domain.Items;</p>
<p>import java.util.List;</p>
<p>public interface ItemsDao {<br>    public List<Items> findAll() throws Exception;<br>}<br>ItemsDaoImpl.java<br>package com.itheima.dao.impl;</p>
<p>import com.itheima.dao.ItemsDao;<br>import com.itheima.domain.Items;</p>
<p>import java.sql.Connection;<br>import java.sql.DriverManager;<br>import java.sql.PreparedStatement;<br>import java.sql.ResultSet;<br>import java.util.ArrayList;<br>import java.util.List;</p>
<p>/**</p>
<ul>
<li>要想从数据库中取出数据</li>
<li>必须有四个属性：数据库驱动，连接数据库的地址，数据库用户名称，数据库密码。<br>*/<br>public class ItemsDaoImpl implements ItemsDao {<br> public List<Items> findAll() throws Exception {<pre><code> List&lt;Items&gt; list = new ArrayList&lt;Items&gt;();
 //先获取connection对象
 Connection connection = null;
 //获取真正操作数据的对象
 PreparedStatement pst = null;
 //执行数据库查询操作
 ResultSet rs = null;
 try &#123;
     //加载驱动类
     Class.forName(&quot;com.mysql.jdbc.Driver&quot;);
     //先获取contection对象
     connection = DriverManager.getConnection(&quot;jdbc:mysql:///maven&quot;, &quot;root&quot;, &quot;root&quot;);
     //获取真正操作数据的对象
     pst = connection.prepareCall(&quot;select * from items&quot;);
     //执行数据库查询操作
     rs = pst.executeQuery();
     //把数据库结果集转成java的List集合
     while (rs.next()) &#123;
         Items items = new Items();
         items.setId(rs.getInt(&quot;id&quot;));
         items.setName(rs.getString(&quot;name&quot;));
         list.add(items);
     &#125;
 &#125; catch (Exception e) &#123;
     e.printStackTrace();
 &#125; finally &#123;
     connection.close();
     pst.close();
     rs.close();
 &#125;
 return list;
</code></pre> }<br>}<br>package com.itheima.domain;<br>package com.itheima.domain;</li>
</ul>
<p>public class Items {<br>    private Integer id;<br>    private String name;</p>
<pre><code>public Integer getId() &#123;
    return id;
&#125;

public void setId(Integer id) &#123;
    this.id = id;
&#125;

public String getName() &#123;
    return name;
&#125;

public void setName(String name) &#123;
    this.name = name;
&#125;
</code></pre><p>}<br>package com.itheima.test;<br>ItemsTest.java<br>package com.itheima.test;</p>
<p>import com.itheima.dao.ItemsDao;<br>import com.itheima.dao.impl.ItemsDaoImpl;<br>import com.itheima.domain.Items;<br>import org.junit.Test;</p>
<p>import java.util.List;</p>
<p>public class ItemsTest {<br>    @Test<br>    public void findAll() throws Exception {<br>        ItemsDao itemsDao = new ItemsDaoImpl();<br>        List<Items> list = itemsDao.findAll();<br>        for (Items items : list) {<br>            System.out.println(items.getName());<br>        }<br>    }<br>}<br>运行结果</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E4%B9%9D%E7%AB%A0Maven%E5%9F%BA%E7%A1%80/" data-id="cl403sxr6001gf8vuh9gral6t" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-Java/第二十八章Redis" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E5%85%AB%E7%AB%A0Redis/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:37:10.059Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="第二十八章Redis"><a href="#第二十八章Redis" class="headerlink" title="第二十八章Redis"></a>第二十八章Redis</h2><h3 id="第1节-Redis环境搭建"><a href="#第1节-Redis环境搭建" class="headerlink" title="第1节 Redis环境搭建"></a>第1节 Redis环境搭建</h3><ul>
<li><p>redis_概述</p>
<ul>
<li><ol>
<li><p>redis</p>
<ul>
<li><ol>
<li><p>概念：redis是一款高性能的NOSQL系列的非关系型数据库</p>
<ul>
<li><p>1.1.什么是NOSQL</p>
<ul>
<li>NoSQL(NoSQL = Not Only SQL)，意即“不仅仅是SQL”，是一项全新的数据库理念，泛指非关系型的数据库。</li>
<li>随着互联网web2.0网站的兴起，传统的关系数据库在应付web2.0网站，特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心，暴露了很多难以克服的问题，而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战，尤其是大数据应用难题。</li>
<li><p>1.1.1 NOSQL和关系型数据库比较</p>
<ul>
<li><p>优点：</p>
<ul>
<li>1）成本：nosql数据库简单易部署，基本都是开源软件，不需要像使用oracle那样花费大量成本购买使用，相比关系型数据库价格便宜。</li>
<li>2）查询速度：nosql数据库将数据存储于缓存之中，关系型数据库将数据存储在硬盘中，自然查询速度远不及nosql数据库。</li>
<li>3）存储数据的格式：nosql的存储格式是key,value形式、文档形式、图片形式等等，所以可以存储基础类型以及对象或者是集合等各种格式，而数据库则只支持基础类型。</li>
<li>4）扩展性：关系型数据库有类似join这样的多表查询机制的限制导致扩展很艰难。</li>
</ul>
</li>
<li><p>缺点：</p>
<ul>
<li>1）维护的工具和资料有限，因为nosql是属于新的技术，不能和关系型数据库十几年的技术同日而语。</li>
<li>2）不提供对sql的支持，如果不支持sql这样的工业标准，将产生一定用户的学习和使用成本。</li>
<li>3）不提供关系型数据库对事务的处理。</li>
</ul>
</li>
</ul>
</li>
<li><p>1.1.2.非关系型数据库的优势：</p>
<ul>
<li>1）性能NOSQL是基于键值对的，可以想象成表中的主键和值的对应关系，而且不需要经过SQL层的解析，所以性能非常高。</li>
<li>2）可扩展性同样也是因为基于键值对，数据之间没有耦合性，所以非常容易水平扩展。</li>
</ul>
</li>
<li><p>1.1.3.关系型数据库的优势：</p>
<ul>
<li>1）复杂查询可以用SQL语句方便的在一个表以及多个表之间做非常复杂的数据查询。</li>
<li>2）事务支持使得对于安全性能很高的数据访问要求得以实现。对于这两类数据库，对方的优势就是自己的弱势，反之亦然。</li>
</ul>
</li>
<li><p>1.1.4.总结</p>
<ul>
<li>关系型数据库与NoSQL数据库并非对立而是互补的关系，即通常情况下使用关系型数据库，在适合使用NoSQL的时候使用NoSQL数据库，</li>
<li>让NoSQL数据库对关系型数据库的不足进行弥补。</li>
<li>一般会将数据存储在关系型数据库中，在nosql数据库中备份存储关系型数据库的数据</li>
</ul>
</li>
</ul>
</li>
<li><p>1.2.主流的NOSQL产品</p>
<ul>
<li><p>键值(Key-Value)存储数据库</p>
<ul>
<li>相关产品： Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB</li>
<li>典型应用： 内容缓存，主要用于处理大量数据的高访问负载。 </li>
<li>数据模型： 一系列键值对</li>
<li>优势： 快速查询</li>
<li>劣势： 存储的数据缺少结构化</li>
</ul>
</li>
<li><p>列存储数据库</p>
<ul>
<li>相关产品：Cassandra, HBase, Riak</li>
<li>典型应用：分布式的文件系统</li>
<li>数据模型：以列簇式存储，将同一列数据存在一起</li>
<li>优势：查找速度快，可扩展性强，更容易进行分布式扩展</li>
<li>劣势：功能相对局限</li>
</ul>
</li>
<li><p>文档型数据库</p>
<ul>
<li>相关产品：CouchDB、MongoDB</li>
<li>典型应用：Web应用（与Key-Value类似，Value是结构化的）</li>
<li>数据模型： 一系列键值对</li>
<li>优势：数据结构要求不严格</li>
<li>劣势： 查询性能不高，而且缺乏统一的查询语法</li>
</ul>
</li>
<li><p>图形(Graph)数据库</p>
<ul>
<li>相关数据库：Neo4J、InfoGrid、Infinite Graph</li>
<li>典型应用：社交网络</li>
<li>数据模型：图结构</li>
<li>优势：利用图结构相关算法。</li>
<li>劣势：需要对整个图做计算才能得出结果，不容易做分布式的集群方案。</li>
</ul>
</li>
</ul>
</li>
<li><p>1.3 什么是Redis</p>
<ul>
<li>Redis是用C语言开发的一个开源的高性能键值对（key-value）数据库，官方提供测试数据，50个并发执行100000个请求,读的速度是110000次/s,写的速度是81000次/s ，且Redis通过提供多种键值数据类型来适应不同场景下的存储需求，</li>
<li><p>Redis支持的键值数据类型如下：</p>
<ul>
<li>1) 字符串类型 string</li>
<li>2) 哈希类型 hash</li>
<li>3) 列表类型 list</li>
<li>4) 集合类型 set</li>
<li>5) 有序集合类型 sortedset</li>
</ul>
</li>
<li><p>1.3.1 redis的应用场景</p>
<ul>
<li>缓存（数据查询、短连接、新闻内容、商品内容等等）</li>
<li>聊天室的在线好友列表</li>
<li>任务队列。（秒杀、抢购、12306等等）</li>
<li>应用排行榜</li>
<li>网站访问统计</li>
<li>数据过期处理（可以精确到毫秒）</li>
<li>分布式集群架构中的session分离</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>下载安装</p>
<ul>
<li><ol>
<li>官网：<a target="_blank" rel="noopener" href="https://redis.io">https://redis.io</a></li>
</ol>
</li>
<li><ol>
<li>中文网：<a target="_blank" rel="noopener" href="http://www.redis.net.cn/">http://www.redis.net.cn/</a></li>
</ol>
</li>
<li><ol>
<li>解压直接可以使用：</li>
</ol>
<ul>
<li><ul>
<li>redis.windows.conf：配置文件</li>
</ul>
</li>
<li><ul>
<li>redis-cli.exe：redis的客户端</li>
</ul>
</li>
<li><ul>
<li>redis-server.exe：redis服务器端</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>命令操作</p>
<ul>
<li><ol>
<li>数据结构</li>
</ol>
<ul>
<li><ul>
<li><p>redis存储的是：key,value格式的数据（键值对），其中key都是字符串，value有5种不同的数据结构。</p>
<ul>
<li><ul>
<li><p>value的数据结构：</p>
<ul>
<li>1) 字符串类型 string：最常用</li>
<li>2) 哈希类型 hash ：map格式  </li>
<li>3) 列表类型 list ：linkedlist格式，支持重复元素</li>
<li>4) 集合类型 set  ：不允许重复元素</li>
<li>5) 有序集合类型 sortedset：不允许重复元素，且元素有顺序</li>
</ul>
</li>
</ul>
</li>
<li><p>字符串类型 string</p>
<ul>
<li><ol>
<li>存储： set key value</li>
</ol>
</li>
<li><ol>
<li>获取： get key</li>
</ol>
</li>
<li><ol>
<li>删除： del key</li>
</ol>
</li>
</ul>
</li>
<li><p>哈希类型 hash</p>
<ul>
<li><ol>
<li>存储： hset key field value</li>
</ol>
</li>
<li><ol>
<li><p>获取： </p>
<ul>
<li><ul>
<li>hget key field: 获取指定的field对应的值</li>
</ul>
</li>
<li><ul>
<li>hgetall key：获取所有的field和value</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li>删除： hdel key field</li>
</ol>
</li>
</ul>
</li>
<li><p>列表类型 list：可以添加一个元素到列表的头部（左边）或者尾部（右边）。</p>
<ul>
<li><ol>
<li><p>添加：</p>
<ul>
<li><ol>
<li>lpush key value：将元素加入列表左表</li>
</ol>
</li>
<li><ol>
<li>rpush key value：将元素加入列表右边</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>获取：</p>
<ul>
<li><ul>
<li>lrange key start end：范围获取</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>删除：</p>
<ul>
<li><ul>
<li>lpop key： 删除列表最左边的元素，并将元素返回。</li>
</ul>
</li>
<li><ul>
<li>rpop key： 删除列表最右边的元素，并将元素返回。</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
<li><p>有序集合类型 sortedset：不允许重复元素，且元素有顺序.每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。</p>
<ul>
<li><ol>
<li>存储：zadd key score value</li>
</ol>
</li>
<li><ol>
<li>获取：zrange key start end [withscores]</li>
</ol>
</li>
<li><ol>
<li>删除：zrem key value</li>
</ol>
</li>
</ul>
</li>
<li><ol>
<li><p>集合类型 set ： 不允许重复元素。</p>
<ul>
<li><ol>
<li>存储：sadd key value</li>
</ol>
</li>
<li><ol>
<li>获取：smembers key:获取set集合中所有元素</li>
</ol>
</li>
<li><ol>
<li>删除：srem key value:删除set集合中的某个元素    </li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>通用命令</p>
<ul>
<li><ol>
<li>keys *：查询所有的键</li>
</ol>
</li>
<li><ol>
<li>type key：获取键对应的value的类型</li>
</ol>
</li>
<li><ol>
<li>del key：删除指定的key value</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>持久化操作</p>
<ul>
<li><ol>
<li>redis是一个内存数据库，当redis服务器重启，获取电脑重启，数据会丢失，我们可以将redis内存中的数据持久化保存到硬盘的文件中。</li>
</ol>
</li>
<li><ol>
<li>redis持久化机制：</li>
</ol>
<ul>
<li><ol>
<li><p>RDB：默认方式，不需要进行配置，默认就使用这种机制。</p>
<ul>
<li><ul>
<li>在一定的间隔时间中，检测key的变化情况，然后持久化数据。</li>
</ul>
</li>
<li><ol>
<li><p>编辑redis.windwos.conf文件</p>
<ul>
<li><h1 id="after-900-sec-15-min-if-at-least-1-key-changed-在15min后，若有1个key发生改变就持久化一次。"><a href="#after-900-sec-15-min-if-at-least-1-key-changed-在15min后，若有1个key发生改变就持久化一次。" class="headerlink" title="after 900 sec (15 min) if at least 1 key changed // 在15min后，若有1个key发生改变就持久化一次。"></a>after 900 sec (15 min) if at least 1 key changed // 在15min后，若有1个key发生改变就持久化一次。</h1></li>
<li>save 900 1</li>
<li><h1 id="after-300-sec-5-min-if-at-least-10-keys-changed-在5min后，若有10个key发生改变就持久化一次。"><a href="#after-300-sec-5-min-if-at-least-10-keys-changed-在5min后，若有10个key发生改变就持久化一次。" class="headerlink" title="after 300 sec (5 min) if at least 10 keys changed // 在5min后，若有10个key发生改变就持久化一次。"></a>after 300 sec (5 min) if at least 10 keys changed // 在5min后，若有10个key发生改变就持久化一次。</h1></li>
<li>save 300 10</li>
<li><h1 id="after-60-sec-if-at-least-10000-keys-changed-在1min后，若有10000个key发生改变就持久化一次。"><a href="#after-60-sec-if-at-least-10000-keys-changed-在1min后，若有10000个key发生改变就持久化一次。" class="headerlink" title="after 60 sec if at least 10000 keys changed // 在1min后，若有10000个key发生改变就持久化一次。"></a>after 60 sec if at least 10000 keys changed // 在1min后，若有10000个key发生改变就持久化一次。</h1></li>
<li>save 60 10000</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>重新启动redis服务器，并指定配置文件名称</p>
<ul>
<li>D:\JavaWeb2018\day23_redis\资料\redis\windows-64\redis-2.8.9&gt;redis-server.exe redis.windows.conf    </li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li>AOF：日志记录的方式，可以记录每一条命令的操作。可以在每一次命令操作后，持久化数据。</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>使用Java客户端操作redis</p>
<ul>
<li><ul>
<li>Jedis: 一款java操作redis数据库的工具。</li>
</ul>
</li>
<li><ul>
<li>使用步骤：</li>
</ul>
<ul>
<li><ol>
<li>下载jedis的jar包</li>
</ol>
</li>
<li><ol>
<li>使用</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
<h3 id="第5节-Jedis连接池"><a href="#第5节-Jedis连接池" class="headerlink" title="第5节 Jedis连接池"></a>第5节 Jedis连接池</h3><ul>
<li>jedis连接池：JedisPool 获取jedis客户端连接时，直接从连接池中获取，对连接有一个更好的复用与管理。</li>
<li><ul>
<li><p>使用：</p>
<ul>
<li><ol>
<li>创建JedisPool连接池对象</li>
</ol>
</li>
<li><ol>
<li>调用方法 getResource()方法获取Jedis连接</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
<li><h1 id="最大活动对象数"><a href="#最大活动对象数" class="headerlink" title="最大活动对象数"></a>最大活动对象数</h1><p>redis.pool.maxTotal=1000    </p>
<h1 id="最大能够保持idel状态的对象数"><a href="#最大能够保持idel状态的对象数" class="headerlink" title="最大能够保持idel状态的对象数"></a>最大能够保持idel状态的对象数</h1><p>redis.pool.maxIdle=100  </p>
<h1 id="最小能够保持idel状态的对象数"><a href="#最小能够保持idel状态的对象数" class="headerlink" title="最小能够保持idel状态的对象数"></a>最小能够保持idel状态的对象数</h1><p>redis.pool.minIdle=50    </p>
<h1 id="当池内没有返回对象时，最大等待时间"><a href="#当池内没有返回对象时，最大等待时间" class="headerlink" title="当池内没有返回对象时，最大等待时间"></a>当池内没有返回对象时，最大等待时间</h1><p>redis.pool.maxWaitMillis=10000    </p>
<h1 id="当调用borrow-Object方法时，是否进行有效性检查"><a href="#当调用borrow-Object方法时，是否进行有效性检查" class="headerlink" title="当调用borrow Object方法时，是否进行有效性检查"></a>当调用borrow Object方法时，是否进行有效性检查</h1><p>redis.pool.testOnBorrow=true    </p>
<h1 id="当调用return-Object方法时，是否进行有效性检查"><a href="#当调用return-Object方法时，是否进行有效性检查" class="headerlink" title="当调用return Object方法时，是否进行有效性检查"></a>当调用return Object方法时，是否进行有效性检查</h1><p>redis.pool.testOnReturn=true  </p>
<h1 id="“空闲链接”检测线程，检测的周期，毫秒数。如果为负值，表示不运行“检测线程”。默认为-1"><a href="#“空闲链接”检测线程，检测的周期，毫秒数。如果为负值，表示不运行“检测线程”。默认为-1" class="headerlink" title="“空闲链接”检测线程，检测的周期，毫秒数。如果为负值，表示不运行“检测线程”。默认为-1."></a>“空闲链接”检测线程，检测的周期，毫秒数。如果为负值，表示不运行“检测线程”。默认为-1.</h1><p>redis.pool.timeBetweenEvictionRunsMillis=30000  </p>
<h1 id="向调用者输出“链接”对象时，是否检测它的空闲超时；"><a href="#向调用者输出“链接”对象时，是否检测它的空闲超时；" class="headerlink" title="向调用者输出“链接”对象时，是否检测它的空闲超时；"></a>向调用者输出“链接”对象时，是否检测它的空闲超时；</h1><p>redis.pool.testWhileIdle=true  </p>
<h1 id="对于“空闲链接”检测线程而言，每次检测的链接资源的个数。默认为3"><a href="#对于“空闲链接”检测线程而言，每次检测的链接资源的个数。默认为3" class="headerlink" title="对于“空闲链接”检测线程而言，每次检测的链接资源的个数。默认为3."></a>对于“空闲链接”检测线程而言，每次检测的链接资源的个数。默认为3.</h1><p>redis.pool.numTestsPerEvictionRun=50  </p>
<h1 id="redis服务器的IP"><a href="#redis服务器的IP" class="headerlink" title="redis服务器的IP"></a>redis服务器的IP</h1><p>redis.ip=xxxxxx  </p>
<h1 id="redis服务器的Port"><a href="#redis服务器的Port" class="headerlink" title="redis服务器的Port"></a>redis服务器的Port</h1><p>redis1.port=6379</p>
</li>
</ul>
<p>Jedis_连接池工具类</p>
<ul>
<li><p>连接池工具类 JedisPoolUtils.java</p>
<ul>
<li><p>/**</p>
<ul>
<li>JedisPool工具类</li>
<li>加载配置文件，配置连接池的参数</li>
<li>提供获取连接的方法<br>*/<br>public class JedisPoolUtils {<br>private static JedisPool jedisPool;</li>
</ul>
<p>static {<br>  //读取配置文件<br>  InputStream is = JedisPoolUtils.class.getClassLoader().getResourceAsStream(“jedis.properties”);<br>  //创建Properties对象<br>  Properties pro = new Properties();<br>  //关联文件<br>  try {</p>
<pre><code>  pro.load(is);
</code></pre><p>  } catch (IOException e) {</p>
<pre><code>  e.printStackTrace();
</code></pre><p>  }<br>  //获取数据，设置到JedisPoolConfig中<br>  JedisPoolConfig config = new JedisPoolConfig();<br>  //pro.getProperty(“maxTotal”)：获取的值是字符串，配置要求的是int值<br>  config.setMaxTotal(Integer.parseInt(pro.getProperty(“maxTotal”)));//最大连接数<br>  config.setMaxIdle(Integer.parseInt(pro.getProperty(“maxIdle”)));//最大空闲连接数<br>  //初始化JedisPool对象<br>  jedisPool = new JedisPool(config, pro.getProperty(“host”), Integer.parseInt(pro.getProperty(“port”)));<br>}</p>
<p>/**</p>
<ul>
<li>获取连接方法<br>*/<br>public static Jedis getJedis() {<br>return jedisPool.getResource();//获取连接<br>}</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="第6节-Redis案例"><a href="#第6节-Redis案例" class="headerlink" title="第6节 Redis案例"></a>第6节 Redis案例</h3><ul>
<li><p>案例_分析&amp;环境搭建</p>
<ul>
<li><p>案例需求：</p>
<ul>
<li><ol>
<li>提供index.html页面，页面中有一个省份（下拉列表）。</li>
</ol>
</li>
<li><ol>
<li>当页面加载完成后，发送ajax请求，加载所有省份。</li>
</ol>
</li>
</ul>
</li>
<li><p>代码</p>
<ul>
<li><p>day23.sql</p>
<ul>
<li>CREATE DATABASE day23; — 创建数据库<br>USE day23;                — 使用数据库<br>CREATE TABLE province(   — 创建表<br>id INT PRIMARY KEY AUTO_INCREMENT,<br>NAME VARCHAR(20) NOT NULL</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>);<br>— 插入数据<br>INSERT INTO province VALUES(NULL,’北京’);<br>INSERT INTO province VALUES(NULL,’上海’);<br>INSERT INTO province VALUES(NULL,’广州’);<br>INSERT INTO province VALUES(NULL,’陕西’);</p>
<pre><code>    - druid.properties

        - driverClassName=com.mysql.jdbc.Driver
</code></pre><p>url=jdbc:mysql:///day23<br>username=root<br>password=root<br>initialSize=5<br>maxActive=10<br>maxWait=3000</p>
<ul>
<li>案例_实现_查询数据库</li>
<li><p>案例_实现_redis缓存优化</p>
<ul>
<li><ul>
<li>注意：使用redis缓存一些不经常发生变化的数据。</li>
</ul>
</li>
<li><ul>
<li>数据库的数据一旦发生改变，则需要更新缓存。</li>
</ul>
</li>
<li><ul>
<li>数据库的表执行“增删改”的相关操作，需要将redis缓存数据清空，再次存入。</li>
</ul>
</li>
<li><ul>
<li>在service对应的增删改方法中，将redis数据删除。</li>
</ul>
</li>
<li><p>ProvinceDaoImpl.java</p>
<ul>
<li>public class ProvinceDaoImpl implements ProvinceDao {<br>//1.声明成员变量 jdbctemplement<br>private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());</li>
</ul>
<p>@Override<br>public List<Province> findAll() {<br>  //1.定义sql<br>  String sql = “select * from province “;<br>  //2.执行sql<br>  List<Province> list = template.query(sql, new BeanPropertyRowMapper<Province>(Province.class));<br>  return list;<br>}<br>}<br>ProvinceDao.java<br>package cn.itcast.dao;</p>
</li>
</ul>
</li>
</ul>
<p>import cn.itcast.domain.Province;</p>
<p>import java.util.List;</p>
<p>public interface ProvinceDao {<br>    public List<Province> findAll();<br>}<br>package cn.itcast.domain;<br>Province.java<br>package cn.itcast.domain;</p>
<p>public class Province {</p>
<pre><code>private int id;
private String name;

public int getId() &#123;
    return id;
&#125;

public void setId(int id) &#123;
    this.id = id;
&#125;

public String getName() &#123;
    return name;
&#125;

public void setName(String name) &#123;
    this.name = name;
&#125;
</code></pre><p>}<br>package cn.itcast.jedis;<br>JedisPoolUtils.java<br>package cn.itcast.jedis.util;</p>
<p>import redis.clients.jedis.Jedis;<br>import redis.clients.jedis.JedisPool;<br>import redis.clients.jedis.JedisPoolConfig;</p>
<p>import java.io.IOException;<br>import java.io.InputStream;<br>import java.util.Properties;</p>
<p>/**</p>
<ul>
<li>JedisPool工具类</li>
<li>加载配置文件，配置连接池的参数</li>
<li><p>提供获取连接的方法<br>*/<br>public class JedisPoolUtils {<br> private static JedisPool jedisPool;</p>
<p> static {</p>
<pre><code> //读取配置文件
 InputStream is = JedisPoolUtils.class.getClassLoader().getResourceAsStream(&quot;jedis.properties&quot;);
 //创建Properties对象
 Properties pro = new Properties();
 //关联文件
 try &#123;
     pro.load(is);
 &#125; catch (IOException e) &#123;
     e.printStackTrace();
 &#125;
 //获取数据，设置到JedisPoolConfig中
 JedisPoolConfig config = new JedisPoolConfig();
 //pro.getProperty(&quot;maxTotal&quot;)：获取的值是字符串，配置要求的是int值
 config.setMaxTotal(Integer.parseInt(pro.getProperty(&quot;maxTotal&quot;)));//最大连接数
 config.setMaxIdle(Integer.parseInt(pro.getProperty(&quot;maxIdle&quot;)));//最大空闲连接数
 //初始化JedisPool对象
 jedisPool = new JedisPool(config, pro.getProperty(&quot;host&quot;), Integer.parseInt(pro.getProperty(&quot;port&quot;)));
</code></pre><p> }</p>
<p> /**</p>
<ul>
<li>获取连接方法<br>*/<br>public static Jedis getJedis() {<br> return jedisPool.getResource();//获取连接<br>}<br>}<br>package cn.itcast.service;<br>ProvinceServiceImpl.java<br>package cn.itcast.service.impl;</li>
</ul>
</li>
</ul>
<p>import cn.itcast.dao.ProvinceDao;<br>import cn.itcast.dao.impl.ProvinceDaoImpl;<br>import cn.itcast.domain.Province;<br>import cn.itcast.jedis.util.JedisPoolUtils;<br>import cn.itcast.service.ProvinceService;<br>import com.fasterxml.jackson.core.JsonProcessingException;<br>import com.fasterxml.jackson.databind.ObjectMapper;<br>import redis.clients.jedis.Jedis;</p>
<p>import java.util.List;</p>
<p>public class ProvinceServiceImpl implements ProvinceService {<br>    //声明dao<br>    private ProvinceDao dao = new ProvinceDaoImpl();</p>
<pre><code>@Override
public List&lt;Province&gt; findAll() &#123;
    return dao.findAll();
&#125;

/**
 * 使用redis缓存
 */
@Override
public String findAllJson() &#123;
    //1.先从redis中查询数据
    //1.1获取redis客户端连接
    Jedis jedis = JedisPoolUtils.getJedis();
    String province_json = jedis.get(&quot;province&quot;);
    //2判断 province_json 数据是否为null
    if (province_json == null || province_json.length() == 0) &#123;
        //redis中没有数据
        System.out.println(&quot;redis中没数据，查询数据库...&quot;);
        //2.1从数据中查询
        List&lt;Province&gt; ps = dao.findAll();
        //2.2将list序列化为json
        ObjectMapper mapper = new ObjectMapper();
        try &#123;
            province_json = mapper.writeValueAsString(ps);
        &#125; catch (JsonProcessingException e) &#123;
            e.printStackTrace();
        &#125;
        //2.3 将json数据存入redis
        jedis.set(&quot;province&quot;, province_json);
        //归还连接
        jedis.close();
    &#125; else &#123;
        System.out.println(&quot;redis中有数据，查询缓存...&quot;);
    &#125;
    return province_json;
&#125;
</code></pre><p>}<br>ProvinceService.java<br>package cn.itcast.service;</p>
<p>import cn.itcast.domain.Province;</p>
<p>import java.util.List;</p>
<p>public interface ProvinceService {<br>    public List<Province> findAll();<br>    public String findAllJson();<br>}<br>package cn.itcast.util;<br>JDBCUtils.java<br>package cn.itcast.util;</p>
<p>import com.alibaba.druid.pool.DruidDataSourceFactory;</p>
<p>import javax.sql.DataSource;<br>import java.io.IOException;<br>import java.io.InputStream;<br>import java.sql.Connection;<br>import java.sql.SQLException;<br>import java.util.Properties;</p>
<p>/**</p>
<ul>
<li><p>JDBC工具类 使用Durid连接池<br>*/<br>public class JDBCUtils {<br> private static DataSource ds;</p>
<p> static {</p>
<pre><code> try &#123;
     //1.加载配置文件
     Properties pro = new Properties();
     //使用ClassLoader加载配置文件，获取字节输入流
     InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream(&quot;druid.properties&quot;);
     pro.load(is);
     //2.初始化连接池对象
     ds = DruidDataSourceFactory.createDataSource(pro);
 &#125; catch (IOException e) &#123;
     e.printStackTrace();
 &#125; catch (Exception e) &#123;
     e.printStackTrace();
 &#125;
</code></pre><p> }</p>
<p> /**</p>
<ul>
<li><p>获取连接池对象<br>*/<br>public static DataSource getDataSource() {<br> return ds;<br>}</p>
<p>/**</p>
</li>
<li>获取连接Connection对象<br>*/<br>public static Connection getConnection() throws SQLException {<br> return ds.getConnection();<br>}<br>}<br>package cn.itcast.web;<br>ProvinceServlet.java<br>package cn.itcast.web.servlet;</li>
</ul>
</li>
</ul>
<p>import cn.itcast.service.ProvinceService;<br>import cn.itcast.service.impl.ProvinceServiceImpl;</p>
<p>import javax.servlet.ServletException;<br>import javax.servlet.annotation.WebServlet;<br>import javax.servlet.http.HttpServlet;<br>import javax.servlet.http.HttpServletRequest;<br>import javax.servlet.http.HttpServletResponse;<br>import java.io.IOException;</p>
<p>@WebServlet(“/provinceServlet”)<br>public class ProvinceServlet extends HttpServlet {<br>    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>       /<em> //1.调用service查询<br>        ProvinceService service = new ProvinceServiceImpl();<br>        List<Province> list = service.findAll();<br>        //2.序列化list为json<br>        ObjectMapper mapper = new ObjectMapper();<br>        String json = mapper.writeValueAsString(list);</em>/</p>
<pre><code>    //1.调用service查询
    ProvinceService service = new ProvinceServiceImpl();
    String json = service.findAllJson();

    System.out.println(json);
    //3.响应结果
    response.setContentType(&quot;application/json;charset=utf-8&quot;);
    response.getWriter().write(json);

&#125;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException &#123;
    this.doPost(request, response);
&#125;
</code></pre><p>}<br>web<br>index.html<br>&lt;!DOCTYPE html&gt;</p>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/jquery-3.3.1.min.js"></script>
    <script>
        $(function () {
            //发送ajax请求，加载所有省份数据
            $.get("provinceServlet", {}, function (data) {
                //[{"id":1,"name":"北京"},{"id":2,"name":"上海"},{"id":3,"name":"广州"},{"id":4,"name":"陕西"}]
                //1.获取select
                var province = $("#province");
                //2.遍历json数组
                $(data).each(function () {
                    //3.创建<option>
                    var option = "<option name='" + this.id + "'>" + this.name + "</option>";
                    //4.调用select的append追加option
                    province.append(option);
                });
            });
        });
    </script>
</head>
<body>
    <select id="province">
        <option>--请选择省份--</option>
    </select>
</body>
</html>


      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E5%85%AB%E7%AB%A0Redis/" data-id="cl403sxr8001kf8vu87tkdtlt" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-Java/第二十七章 Ajax和JSON" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E4%B8%83%E7%AB%A0%20Ajax%E5%92%8CJSON/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:36:58.240Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="第二十七章-Ajax和JSON"><a href="#第二十七章-Ajax和JSON" class="headerlink" title="第二十七章 Ajax和JSON"></a>第二十七章 Ajax和JSON</h2>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E4%B8%83%E7%AB%A0%20Ajax%E5%92%8CJSON/" data-id="cl403sxr4001df8vuhvv2ggyk" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-Java/第二十六章Jquery" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E5%85%AD%E7%AB%A0Jquery/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:36:48.588Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="第二十六章Jquery"><a href="#第二十六章Jquery" class="headerlink" title="第二十六章Jquery"></a>第二十六章Jquery</h2>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E5%85%AD%E7%AB%A0Jquery/" data-id="cl403sxr7001jf8vu4p0baj8s" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-Java/第二十五章 Filter和Listener" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E4%BA%94%E7%AB%A0%20Filter%E5%92%8CListener/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:36:38.805Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="第二十五章-Filter和Listener"><a href="#第二十五章-Filter和Listener" class="headerlink" title="第二十五章 Filter和Listener"></a>第二十五章 Filter和Listener</h2>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E4%BA%94%E7%AB%A0%20Filter%E5%92%8CListener/" data-id="cl403sxr7001if8vu1py398tw" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-Java/第二十四章 综合案例(用户信息)" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E5%9B%9B%E7%AB%A0%20%E7%BB%BC%E5%90%88%E6%A1%88%E4%BE%8B(%E7%94%A8%E6%88%B7%E4%BF%A1%E6%81%AF)/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:36:19.802Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="第二十四章-综合案例-用户信息"><a href="#第二十四章-综合案例-用户信息" class="headerlink" title="第二十四章 综合案例(用户信息)"></a>第二十四章 综合案例(用户信息)</h2>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E5%9B%9B%E7%AB%A0%20%E7%BB%BC%E5%90%88%E6%A1%88%E4%BE%8B(%E7%94%A8%E6%88%B7%E4%BF%A1%E6%81%AF)/" data-id="cl403sxr9001lf8vu1uf7fl83" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-Java/第二十三章JSP、EL和JSTL" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E4%B8%89%E7%AB%A0JSP%E3%80%81EL%E5%92%8CJSTL/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:36:13.354Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="第二十三章JSP、EL和JSTL"><a href="#第二十三章JSP、EL和JSTL" class="headerlink" title="第二十三章JSP、EL和JSTL"></a>第二十三章JSP、EL和JSTL</h2>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E4%B8%89%E7%AB%A0JSP%E3%80%81EL%E5%92%8CJSTL/" data-id="cl403sxr5001ff8vu0q6c2cwi" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-Java/第二十二章Request和Response" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E4%BA%8C%E7%AB%A0Request%E5%92%8CResponse/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:35:56.208Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="第二十二章Request和Response"><a href="#第二十二章Request和Response" class="headerlink" title="第二十二章Request和Response"></a>第二十二章Request和Response</h2><h3 id="01-Request-原理和继承体系"><a href="#01-Request-原理和继承体系" class="headerlink" title="01 Request_原理和继承体系"></a>01 Request_原理和继承体系</h3><ul>
<li><p>Request_原理</p>
<ul>
<li><ol>
<li><p>request对象和response对象的原理</p>
<ul>
<li><ol>
<li>request和response对象是由服务器创建的。我们来使用它们。</li>
</ol>
</li>
<li><ol>
<li>request对象是来获取请求消息，response对象是来设置响应消息。</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
<li><p>Request_继承体系</p>
<ul>
<li><ol>
<li><p>request对象和response对象的原理</p>
<ul>
<li><ol>
<li>request和response对象是由服务器创建的。我们来使用它们。</li>
</ol>
</li>
<li><ol>
<li>request对象是来获取请求消息，response对象是来设置响应消息。</li>
</ol>
</li>
<li><p>代码</p>
<ul>
<li>package cn.itcast.web.request;</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
<p>import javax.servlet.ServletException;<br>import javax.servlet.annotation.WebServlet;<br>import javax.servlet.http.HttpServlet;<br>import javax.servlet.http.HttpServletRequest;<br>import javax.servlet.http.HttpServletResponse;<br>import java.io.IOException;</p>
<p>/**</p>
<ul>
<li><p>演示Request对象获取请求行数据<br>*/<br>@WebServlet(“/requestDemo1”)<br>public class RequestDemo1 extends HttpServlet {<br> protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br> }<br> protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {</p>
<pre><code> /*
     1. 获取请求方式 ：GET
         * String getMethod()
     2. (*)获取虚拟目录：/day14
         * String getContextPath()
     3. 获取Servlet路径: /requestDemo1
         * String getServletPath()
     4. 获取get方式请求参数：name=zhangsan
         * String getQueryString()
     5. (*)获取请求URI：/day14/demo1
         * String getRequestURI():        /day14/requestDemo1
         * StringBuffer getRequestURL()  :http://localhost/day14/requestDemo1
     6. 获取协议及版本：HTTP/1.1
         * String getProtocol()
     7. 获取客户机的IP地址：
         * String getRemoteAddr()
  */
 //1. 获取请求方式 ：GET
 String method = request.getMethod();
 System.out.println(method);
 //2.(*)获取虚拟目录：/day14
 String contextPath = request.getContextPath();
 System.out.println(contextPath);
 //3. 获取Servlet路径: /demo1
 String servletPath = request.getServletPath();
 System.out.println(servletPath);
 //4. 获取get方式请求参数：name=zhangsan
 String queryString = request.getQueryString();
 System.out.println(queryString);
 //5.(*)获取请求URI：/day14/demo1
 String requestURI = request.getRequestURI();
 StringBuffer requestURL = request.getRequestURL();
 System.out.println(requestURI);
 System.out.println(requestURL);
 //6. 获取协议及版本：HTTP/1.1
 String protocol = request.getProtocol();
 System.out.println(protocol);
 //7. 获取客户机的IP地址：
 String remoteAddr = request.getRemoteAddr();
 System.out.println(remoteAddr);
</code></pre><p> }</p>
<ul>
<li><ol>
<li><p>request对象继承体系结构：    </p>
<ul>
<li>ServletRequest         —    接口<br>|    继承<br>HttpServletRequest  — 接口<br>|    实现<br>org.apache.catalina.connector.RequestFacade 类(tomcat)</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>request功能：</p>
<ul>
<li><ol>
<li><p>获取请求消息数据</p>
<ul>
<li><ol>
<li>获取请求行数据</li>
</ol>
<ul>
<li><ul>
<li>GET /day14/demo1?name=zhangsan HTTP/1.1</li>
</ul>
</li>
<li><ul>
<li><p>方法：</p>
<ul>
<li><ol>
<li><p>获取请求方式 ：GET</p>
<ul>
<li><ul>
<li>String getMethod()  </li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>(*)获取虚拟目录：/day14</p>
<ul>
<li><ul>
<li>String getContextPath()</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>获取Servlet路径: /demo1</p>
<ul>
<li><ul>
<li>String getServletPath()</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>获取get方式请求参数：name=zhangsan</p>
<ul>
<li><ul>
<li>String getQueryString()</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>(*)获取请求URI：/day14/demo1</p>
<ul>
<li><ul>
<li>String getRequestURI()：           /day14/demo1</li>
</ul>
</li>
<li><ul>
<li>StringBuffer getRequestURL()：<a target="_blank" rel="noopener" href="http://localhost/day14/demo1">http://localhost/day14/demo1</a></li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>获取协议及版本：HTTP/1.1</p>
<ul>
<li><ul>
<li>String getProtocol()</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>获取客户机的IP地址：</p>
<ul>
<li><ul>
<li>String getRemoteAddr()</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><ol>
<li>获取请求头数据</li>
</ol>
<ul>
<li><ul>
<li><p>方法：</p>
<ul>
<li><ul>
<li>(*)String getHeader(String name)：通过请求头的名称获取请求头的值</li>
</ul>
</li>
<li><ul>
<li>Enumeration<String> getHeaderNames()：获取所有的请求头名称</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>package cn.itcast.web.request;</p>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
<p>import javax.servlet.ServletException;<br>import javax.servlet.annotation.WebServlet;<br>import javax.servlet.http.HttpServlet;<br>import javax.servlet.http.HttpServletRequest;<br>import javax.servlet.http.HttpServletResponse;<br>import java.io.IOException;<br>import java.util.Enumeration;</p>
<p>@WebServlet(“/requestDemo2”)<br>public class RequestDemo2 extends HttpServlet {<br>    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>    }<br>    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>        //演示获取请求头数据<br>        //1.获取所有请求头名称<br>        Enumeration<String> headerNames = request.getHeaderNames();<br>        //2.遍历<br>        while (headerNames.hasMoreElements()) {<br>            String name = headerNames.nextElement();<br>            //根据名称获取请求头的值<br>            String value = request.getHeader(name);<br>            System.out.println(name + “—-“ + value);<br>        }<br>    }<br>}</p>
<p>package cn.itcast.web.request;</p>
<p>import javax.servlet.ServletException;<br>import javax.servlet.annotation.WebServlet;<br>import javax.servlet.http.HttpServlet;<br>import javax.servlet.http.HttpServletRequest;<br>import javax.servlet.http.HttpServletResponse;<br>import java.io.IOException;<br>import java.util.Enumeration;</p>
<p>@WebServlet(“/requestDemo3”)<br>public class RequestDemo3 extends HttpServlet {<br>    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>    }<br>    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>        //演示获取请求头数据：user-agent 告诉服务器客户端的版本是什么—&gt;判断浏览器版本<br>        String agent = request.getHeader(“user-agent”); // user-agent不区分大小写<br>        //判断agent的浏览器版本<br>        if (agent.contains(“Chrome”)) {<br>            //谷歌<br>            System.out.println(“谷歌来了…”);<br>        } else if (agent.contains(“Firefox”)) {<br>            //火狐<br>            System.out.println(“火狐来了…”);<br>        }<br>    }<br>}<br>演示获取请求头数据、防盗链</p>
<pre><code>            - 
</code></pre><p>package cn.itcast.web.request;</p>
<p>import javax.servlet.ServletContext;<br>import javax.servlet.ServletException;<br>import javax.servlet.annotation.WebServlet;<br>import javax.servlet.http.HttpServlet;<br>import javax.servlet.http.HttpServletRequest;<br>import javax.servlet.http.HttpServletResponse;<br>import java.io.IOException;</p>
<p>@WebServlet(“/requestDemo4”)<br>public class RequestDemo4 extends HttpServlet {<br>    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>    }</p>
<pre><code>protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException &#123;
    //演示获取请求头数据:referer
    String referer = request.getHeader(&quot;referer&quot;);
    System.out.println(referer);//http://localhost/day14/login.html
    //防盗链
    if (referer != null) &#123;
        if (referer.contains(&quot;/day14&quot;)) &#123;
            //正常访问
</code></pre><p>//                 System.out.println(“播放电影….”);<br>                response.setContentType(“text/html;charset=utf-8”);<br>                response.getWriter().write(“播放电影….”);<br>            } else {<br>                //盗链<br>//                System.out.println(“想看电影吗？来优酷吧…”);<br>                response.setContentType(“text/html;charset=utf-8”);<br>                response.getWriter().write(“想看电影吗？来优酷吧…”);<br>            }<br>        }<br>    }<br>}</p>
<pre><code>        - 3. 获取请求体数据

            - 获取所有请求头名称

                - * 请求体：只有POST请求方式，才有请求体，在请求体中封装了POST请求的请求参数
                - * 步骤：
                - 1. 获取流对象

                    - *  BufferedReader getReader()：获取字符输入流，只能操作字符数据
                    - *  ServletInputStream getInputStream()：获取字节输入流，可以操作所有类型数据
                    - * 在文件上传知识点后讲解

                - 2. 再从流对象中拿数据

                    -  
</code></pre><p>import javax.servlet.ServletException;<br>import javax.servlet.annotation.WebServlet;<br>import javax.servlet.http.HttpServlet;<br>import javax.servlet.http.HttpServletRequest;<br>import javax.servlet.http.HttpServletResponse;<br>import java.io.BufferedReader;<br>import java.io.IOException;</p>
<p>@WebServlet(“/requestDemo5”)<br>public class RequestDemo5 extends HttpServlet {<br>    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>        //获取请求消息体—请求参数<br>        //1.获取字符流<br>        BufferedReader br = request.getReader();<br>        //2.读取数据<br>        String line = null;<br>        while ((line = br.readLine()) != null) {<br>            System.out.println(line);<br>        }<br>    }<br>    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>    }<br>}</p>
<pre><code>    - 2. 其他功能：

        - 1. 获取请求参数通用方式：不论get还是post请求方式都可以使用下列方法来获取请求参数。

            - 1. String getParameter(String name)：根据参数名称获取参数值 username=zs&amp;password=123
            - 2. String[] getParameterValues(String name)：根据参数名称获取参数值的数组 hobby=xx&amp;hobby=game
            - 3. Enumeration&lt;String&gt; getParameterNames()：获取所有请求的参数名称
            - 4. Map&lt;String,String[]&gt; getParameterMap()：获取所有参数的map集合
            - @WebServlet(&quot;/requestDemo6&quot;)
</code></pre><p>public class RequestDemo6 extends HttpServlet {<br>    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>        //post 获取请求参数</p>
<pre><code>    //根据参数名称获取参数值
    /* String username = request.getParameter(&quot;username&quot;);
    System.out.println(&quot;post&quot;);
    System.out.println(username);*/

    //根据参数名称获取参数值的数组
    String[] hobbies = request.getParameterValues(&quot;hobby&quot;);
    /*for (String hobby : hobbies) &#123;
        System.out.println(hobby);
    &#125;*/

    //获取所有请求的参数名称
    /*Enumeration&lt;String&gt; parameterNames = request.getParameterNames();
    while(parameterNames.hasMoreElements())&#123;
        String name = parameterNames.nextElement();
        System.out.println(name);
        String value = request.getParameter(name);
        System.out.println(value);
        System.out.println(&quot;----------------&quot;);
    &#125;*/

    // 获取所有参数的map集合
    Map&lt;String, String[]&gt; parameterMap = request.getParameterMap();
    //遍历
    Set&lt;String&gt; keyset = parameterMap.keySet();
    for (String name : keyset) &#123;
        //获取键 获取值
        String[] values = parameterMap.get(name);
        System.out.println(name);
        for (String value : values) &#123;
            System.out.println(value);
        &#125;
        System.out.println(&quot;-----------------&quot;);
    &#125;
&#125;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException &#123;
    //get 获取请求参数
   /* //根据参数名称获取参数值
    String username = request.getParameter(&quot;username&quot;);
    System.out.println(&quot;get&quot;);
    System.out.println(username);*/
    this.doPost(request, response);
&#125;
</code></pre><p>}</p>
<pre><code>            - 中文乱码问题：

                -     * get方式：tomcat 8 已经将get方式乱码问题解决了。
                -     * post方式：会乱码
                -         * 解决：在获取参数前，设置request的编码 request.setCharacterEncoding(&quot;utf-8&quot;) ;
                - get方法（tomcat 8 已经将get方式乱码问题解决）
                - post方式（设置request的编码）

        - 2. 请求转发

            - 1. 步骤：

                - 1. 通过request对象获取请求转发器对象：RequestDispatcher getRequestDispatcher(String path)
                - 2. 使用RequestDispatcher对象来进行转发：forward(ServletRequest request, ServletResponse response)

            - 2. 特点：

                - 1. 浏览器地址栏路径不发生变化。
                - 2. 只能转发到当前服务器内部资源中。
                - 3. 转发是一次请求。

        - 3. 共享数据

            - * 域对象：一个有作用范围的对象，可以在范围内共享数据
            - * request域：代表一次请求的范围，一般用于请求转发的多个资源中共享数据
            - * 方法：

                - 1. void setAttribute(String name,Object obj)：存储数据
                - 2. Object getAttitude(String name)：通过键获取值
                - 3. void removeAttribute(String name)：通过键移除键值对

        - 4. 获取ServletContext

            - * ServletContext getServletContext()
</code></pre><h3 id="05-request登录案例"><a href="#05-request登录案例" class="headerlink" title="05 request登录案例"></a>05 request登录案例</h3><ul>
<li><ul>
<li><p>用户登录案例需求：</p>
<ul>
<li><p>1.编写login.html登录页面</p>
<ul>
<li>username &amp; password 两个输入框</li>
</ul>
</li>
<li><p>2.使用Druid数据库连接池技术,操作mysql，day14数据库中user表</p>
</li>
<li>3.使用JdbcTemplate技术封装JDBC</li>
<li>4.登录成功跳转到SuccessServlet展示：登录成功！用户名,欢迎您</li>
<li>5.登录失败跳转到FailServlet展示：登录失败，用户名或密码错误</li>
</ul>
</li>
</ul>
</li>
<li><p>开发步骤</p>
<ul>
<li><p>1：创建项目，导入html页面，配置文件，jar包</p>
<ul>
<li>子主题 1</li>
</ul>
</li>
<li><p>开发步骤2：创建数据库环境</p>
<ul>
<li>CREATE DATABASE day14;</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>USE day14;</p>
<p>CREATE TABLE USER(<br>    id INT PRIMARY KEY AUTO_INCREMENT,<br>    username VARCHAR(32) UNIQUE NOT NULL,<br>    PASSWORD VARCHAR(32) NOT NULL<br>);</p>
<pre><code>- 开发步骤4：创建包cn.itcast.util，编写工具类JDBCUtils

    - package cn.itcast.util;
</code></pre><p>import com.alibaba.druid.pool.DruidDataSourceFactory;</p>
<p>import javax.sql.DataSource;<br>import javax.xml.crypto.Data;<br>import java.io.IOException;<br>import java.io.InputStream;<br>import java.sql.Connection;<br>import java.sql.SQLException;<br>import java.util.Properties;</p>
<p>/**</p>
<ul>
<li><p>JDBC工具类 使用Durid连接池<br>*/<br>public class JDBCUtils {<br> private static DataSource ds;<br> static {</p>
<pre><code> try &#123;
     //1.加载配置文件
     Properties pro = new Properties();
     //使用ClassLoader加载配置文件，获取字节输入流
     InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream(&quot;druid.properties&quot;);
     pro.load(is);
     //2.初始化连接池对象
     ds = DruidDataSourceFactory.createDataSource(pro);
 &#125; catch (IOException e) &#123;
     e.printStackTrace();
 &#125; catch (Exception e) &#123;
     e.printStackTrace();
 &#125;
</code></pre><p> }</p>
<p> /**</p>
<ul>
<li><p>获取连接池对象<br>*/<br>public static DataSource getDataSource() {<br> return ds;<br>}</p>
<p>/**</p>
</li>
<li><p>获取连接Connection对象<br>*/<br>public static Connection getConnection() throws SQLException {<br> return ds.getConnection();<br>}</p>
<ul>
<li><p>开发步骤5：创建包cn.itcast.dao，创建类UserDao，提供login方法</p>
<ul>
<li>// 调用query方法<br>User user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), loginUser.getUsername(), loginUser.getPassword());<br>————————————————</li>
<li>/**</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>操作数据库中User表的类——增删改查方法全在此类中<br><em>/<br>public class UserDao {<br> //声明JDBCTemplate对象共用<br> private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());<br> /*</em></p>
<ul>
<li>登录方法<br>*</li>
<li>@param loginUser 只有用户名和密码</li>
<li><p>@return user包含用户全部数据, 没有查询到，返回null<br>*/<br>public User login(User loginUser) {<br> try {</p>
<pre><code> //1.编写sql
 String sql = &quot;select * from user where username = ? and password = ?&quot;;
 //2.调用query方法
 User user = template.queryForObject(sql,
         new BeanPropertyRowMapper&lt;User&gt;(User.class),
         loginUser.getUsername(), loginUser.getPassword());
 return user;
</code></pre><p> } catch (DataAccessException e) {</p>
<pre><code> e.printStackTrace(); // 记录日志
 return null;
</code></pre><p> }<br>}<br>}<br>测试login()方法</p>
<ul>
<li><p>​开发步骤6： 编写cn.itcast.web.servlet.LoginServlet类</p>
<ul>
<li>@WebServlet(“/loginServlet”)<br>public class LoginServlet extends HttpServlet {<br>@Override<br>protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {<br>//1.设置编码<br>req.setCharacterEncoding(“utf-8”);<br>/<em> //2.获取请求参数<br>String username = req.getParameter(“username”);<br>String password = req.getParameter(“password”);<br>//3.封装user对象<br>User loginUser = new User();<br>loginUser.setUsername(username);<br>loginUser.setPassword(password);</em>/<br>//2.获取所有请求参数<br>Map<String, String[]> map = req.getParameterMap();<br>//3.创建User对象<br>User loginUser = new User();<br>//3.2使用BeanUtils封装<br>try {<br> BeanUtils.populate(loginUser, map);<br>} catch (IllegalAccessException e) {<br> e.printStackTrace();<br>} catch (InvocationTargetException e) {<br> e.printStackTrace();<br>}</li>
</ul>
<p>//4.调用UserDao的login方法<br>UserDao dao = new UserDao();<br>User user = dao.login(loginUser);</p>
<p>//5.判断user<br>if (user == null) {<br>   //登录失败<br>   req.getRequestDispatcher(“/failServlet”).forward(req, resp);<br>} else {<br>   //登录成功<br>   //存储数据<br>   req.setAttribute(“user”, user);<br>   //转发<br>   req.getRequestDispatcher(“/successServlet”).forward(req, resp);<br>}<br>}</p>
</li>
</ul>
<p>@Override<br>protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {<br> this.doGet(req, resp);<br>}<br>}</p>
<ul>
<li><p>​开发步骤7：编写FailServlet和SuccessServlet类</p>
<ul>
<li>@WebServlet(“/successServlet”)<br>public class SuccessServlet extends HttpServlet {<br>protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>//获取request域中共享的user对象<br>User user = (User) request.getAttribute(“user”);<br>if(user != null){<br> //给页面写一句话<br> //设置编码<br> response.setContentType(“text/html;charset=utf-8”);<br> //输出<br> response.getWriter().write(“登录成功！”+user.getUsername()+”,欢迎您！”);<br>}<br>}<br>protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>this.doPost(request,response);<br>}<br>}<br>FailServlet.java：</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>package cn.itcast.web.servlet;</p>
<p>import javax.servlet.ServletException;<br>import javax.servlet.annotation.WebServlet;<br>import javax.servlet.http.HttpServlet;<br>import javax.servlet.http.HttpServletRequest;<br>import javax.servlet.http.HttpServletResponse;<br>import java.io.IOException;</p>
<p>@WebServlet(“/failServlet”)<br>public class FailServlet extends HttpServlet {<br>    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>        //给页面写一句话<br>        //设置编码<br>        response.setContentType(“text/html;charset=utf-8”);<br>        //输出<br>        response.getWriter().write(“登录失败，用户名或密码错误！”);<br>    }<br>    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>        this.doPost(request,response);<br>    }<br>}</p>
<pre><code>- 开发步骤8：login.html中form表单的action路径的写法
- 开发步骤9：BeanUtils工具类，简化数据封装

    - 子主题 9
    - 子主题 10
    - 子主题 11
    - 子主题 12
</code></pre><ul>
<li><p>登录案例_BeanUtils介绍</p>
<ul>
<li><ul>
<li><p>用于封装JavaBean的</p>
<ul>
<li><ol>
<li><p>JavaBean：标准的Java类</p>
<ul>
<li><ol>
<li><p>要求：</p>
<ul>
<li><ol>
<li>类必须被public修饰</li>
</ol>
</li>
<li><ol>
<li>必须提供空参的构造器</li>
</ol>
</li>
<li><ol>
<li>成员变量必须使用private修饰</li>
</ol>
</li>
<li><ol>
<li>提供公共setter和getter方法</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li>功能：封装数据</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>概念：</p>
<ul>
<li><p>成员变量：</p>
<ul>
<li>属性：setter和getter方法截取后的产物</li>
</ul>
</li>
<li><p>例如：getUsername() —&gt; Username—&gt; username</p>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>方法：</p>
<ul>
<li><ol>
<li>setProperty()</li>
</ol>
</li>
<li><ol>
<li>getProperty()</li>
</ol>
</li>
<li><ol>
<li>populate(Object obj, Map map):将map集合的键值对信息，封装到对应的JavaBean对象中</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="06-HTTP响应协议"><a href="#06-HTTP响应协议" class="headerlink" title="06 HTTP响应协议"></a>06 HTTP响应协议</h3><ul>
<li><ol>
<li><p>请求消息：客户端发送给服务器端的数据。</p>
<ul>
<li><ul>
<li><p>数据格式：</p>
<ul>
<li><ol>
<li>请求行</li>
</ol>
</li>
<li><ol>
<li>请求头</li>
</ol>
</li>
<li><ol>
<li>请求空行</li>
</ol>
</li>
<li><ol>
<li>请求体</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>响应消息：服务器端发送给客户端的数据。</p>
<ul>
<li><ul>
<li><p>数据格式：</p>
<ul>
<li><ol>
<li>响应行</li>
</ol>
</li>
<li><ol>
<li>响应头</li>
</ol>
</li>
<li><ol>
<li>响应空行</li>
</ol>
</li>
<li><ol>
<li>响应体</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><p>响应字符串格式</p>
<ul>
<li>HTTP/1.1 200 OK<br>Content-Type: text/html;charset=UTF-8<br>Content-Length: 101<br>Date: Wed, 06 Jun 2018 07:08:42 GMT</li>
</ul>
<html>
 <head>
   <title>$Title$</title>
 </head>
 <body>
 hello , response
 </body>
</html>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><p>响应消息：服务器端发送给客户端的数据。</p>
<ul>
<li><ul>
<li><p>数据格式：</p>
<ul>
<li><ol>
<li><p>响应行</p>
<ul>
<li><ol>
<li>组成：协议/版本 响应状态码 状态码描述</li>
</ol>
</li>
<li><ol>
<li><p>响应状态码：服务器告诉客户端浏览器本次请求和响应的一个状态。</p>
<ul>
<li><ol>
<li>状态码都是3位数字 </li>
</ol>
</li>
<li><ol>
<li>分类：</li>
</ol>
<ul>
<li><ol>
<li>1xx：服务器就收客户端消息，但没有接受完成，等待一段时间后，发送1xx多状态码</li>
</ol>
</li>
<li><ol>
<li>2xx：成功。代表：200</li>
</ol>
</li>
<li><ol>
<li>3xx：重定向。代表：302(重定向)，304(访问缓存)</li>
</ol>
</li>
<li><ol>
<li><p>4xx：客户端错误。</p>
<ul>
<li><ul>
<li><p>代表：</p>
<ul>
<li><ul>
<li>404：请求路径没有对应的资源</li>
</ul>
</li>
<li><ul>
<li>405：请求方式没有对应的doXxx方法</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li>5xx：服务器端错误。代表：500(服务器内部出现异常)</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>响应头：</p>
<ul>
<li><ol>
<li>格式：头名称： 值</li>
</ol>
</li>
<li><ol>
<li><p>常见的响应头：</p>
<ul>
<li><ol>
<li>Content-Type：服务器告诉客户端本次响应体数据格式以及编码格式。</li>
</ol>
</li>
<li><ol>
<li><p>Content-disposition：服务器告诉客户端以什么格式打开响应体数据。</p>
<ul>
<li><ul>
<li>值：</li>
</ul>
<ul>
<li><ul>
<li>in-line：默认值，在当前页面内打开</li>
</ul>
</li>
<li><ul>
<li>attachment;filename=xxx：以附件形式打开响应体。（应用：文件下载）</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
<h3 id="07-response之重定向"><a href="#07-response之重定向" class="headerlink" title="07 response之重定向"></a>07 response之重定向</h3><ul>
<li><ul>
<li><p>Response对象 功能：设置响应消息。</p>
<ul>
<li><ol>
<li><p>设置响应行</p>
<ul>
<li><ol>
<li>格式：HTTP/1.1 200 ok</li>
</ol>
</li>
<li><ol>
<li>设置状态码：setStatus(int sc) </li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li>设置响应头：setHeader(String name, String value) </li>
</ol>
</li>
<li><ol>
<li><p>设置响应体：</p>
<ul>
<li><ul>
<li><p>使用步骤：</p>
<ul>
<li><ol>
<li><p>获取输出流</p>
<ul>
<li><ul>
<li>字符输出流：PrintWriter getWriter()</li>
</ul>
</li>
<li><ul>
<li>字节输出流：ServletOutputStream getOutputStream()</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li>使用输出流，将数据输出到客户端浏览器</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><p>案例：</p>
<ul>
<li><ol>
<li><p>完成重定向</p>
<ul>
<li><ul>
<li>重定向：资源跳转的方式</li>
</ul>
</li>
<li><ul>
<li><p>代码实现：</p>
<ul>
<li>//1. 设置状态码为302<br>response.setStatus(302);<br>//2.设置响应头location<br>response.setHeader(“location”,”/day15/responseDemo2”);</li>
</ul>
<p>//简单的重定向方法<br>response.sendRedirect(“/day15/responseDemo2”)</p>
</li>
</ul>
</li>
<li><ul>
<li><p>重定向的特点：redirect</p>
<ul>
<li><ol>
<li>地址栏发生变化</li>
</ol>
</li>
<li><ol>
<li>重定向可以访问其他站点(服务器)的资源</li>
</ol>
</li>
<li><ol>
<li>重定向是两次请求，不能使用request对象来共享数据。</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><p>转发的特点：forward</p>
<ul>
<li><ol>
<li>转发地址栏路径不变</li>
</ol>
</li>
<li><ol>
<li>转发只能访问当前服务器下的资源</li>
</ol>
</li>
<li><ol>
<li>转发是一次请求，可以使用request对象来共享数据。</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li>forward(转发)和redirect(重定向)区别</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li>服务器输出字符数据到浏览器</li>
</ol>
</li>
<li><ol>
<li>服务器输出字节数据到浏览器</li>
</ol>
</li>
<li><ol>
<li>验证码</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="08-response之相对路径和绝对路径"><a href="#08-response之相对路径和绝对路径" class="headerlink" title="08 response之相对路径和绝对路径"></a>08 response之相对路径和绝对路径</h3><ul>
<li><ol>
<li><p>完成重定向    </p>
<ul>
<li><ul>
<li><p>路径写法：</p>
<ul>
<li><ol>
<li><p>路径分类</p>
<ul>
<li><ol>
<li>相对路径：通过相对路径不可以确定唯一资源。</li>
</ol>
<ul>
<li><ul>
<li>如：./index.html</li>
</ul>
</li>
<li><ul>
<li>不以/开头，以.开头路径</li>
</ul>
</li>
<li><ul>
<li><p>规则：找到当前资源和目标资源之间的相对位置关系。</p>
<ul>
<li><ul>
<li>./：当前目录</li>
</ul>
</li>
<li><ul>
<li>../:后退一级目录</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><ol>
<li>绝对路径：通过绝对路径可以确定唯一资源。</li>
</ol>
<ul>
<li><ul>
<li>如：<a target="_blank" rel="noopener" href="http://localhost/day15/responseDemo2">http://localhost/day15/responseDemo2</a> ； 省略协议、域名、端口：/day15/responseDemo2</li>
</ul>
</li>
<li><ul>
<li>以/开头的路径</li>
</ul>
</li>
<li><ul>
<li>给客户端浏览器使用：需要加虚拟目录(项目的访问路径)。</li>
</ul>
</li>
<li><ul>
<li>建议虚拟目录动态获取：request.getContextPath()</li>
</ul>
</li>
<li><ul>
<li><a>、<form>、重定向 …</li>
</ul>
</li>
<li><ul>
<li>给服务器使用：不需要加虚拟目录。</li>
</ul>
</li>
<li><ul>
<li>转发路径</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
<h3 id="09-response之输出数据"><a href="#09-response之输出数据" class="headerlink" title="09 response之输出数据"></a>09 response之输出数据</h3><ul>
<li><ul>
<li><p>案例：</p>
<ul>
<li><ol>
<li>完成重定向</li>
</ol>
</li>
<li><ol>
<li><p>服务器输出字符数据到浏览器</p>
<ul>
<li><ul>
<li><p>步骤：</p>
<ul>
<li><ol>
<li>获取字符输出流（流向客户端浏览器）</li>
</ol>
</li>
<li><ol>
<li><p>输出数据</p>
<ul>
<li><ul>
<li>注意：</li>
</ul>
<ul>
<li><ul>
<li><p>乱码问题：</p>
<ul>
<li><ol>
<li>PrintWriter pw = response.getWriter();获取的流的默认编码是ISO-8859-1</li>
</ol>
</li>
<li><ol>
<li>设置该流的默认编码</li>
</ol>
</li>
<li><ol>
<li><p>告诉浏览器响应体使用的编码</p>
<ul>
<li>//简单的形式，设置编码，是在获取流之前设置<br>response.setContentType(“text/html;charset=utf-8”);</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><p>@WebServlet(“/responseDemo4”)<br>public class ResponseDemo4 extends HttpServlet {<br>protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>  //获取流对象之前，设置流的默认编码：ISO-8859-1 设置为：GBK<br>  //response.setCharacterEncoding(“utf-8”);<br>  //告诉浏览器，服务器发送的消息体数据的编码。建议浏览器使用该编码解码<br>  //response.setHeader(“content-type”,”text/html;charset=utf-8”);</p>
<p>  //简单的形式，设置编码<br>  response.setContentType(“text/html;charset=utf-8”);</p>
<p>  //1.获取字符输出流<br>  PrintWriter pw = response.getWriter();<br>  //2.输出数据<br>  //pw.write(“<h1>hello response</h1>“);<br>  pw.write(“你好啊啊啊 response”);<br>}</p>
</li>
</ul>
<p>protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {</p>
<pre><code>this.doPost(request, response);
</code></pre><p>}<br>}</p>
<ul>
<li><ol>
<li><p>服务器输出字节数据到浏览器</p>
<ul>
<li><ul>
<li><p>步骤：</p>
<ul>
<li><ol>
<li>获取字节输出流</li>
</ol>
</li>
<li><ol>
<li>输出数据</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li>验证码</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="10-response之验证码"><a href="#10-response之验证码" class="headerlink" title="10 response之验证码"></a>10 response之验证码</h3><ul>
<li><p>Response 对象 </p>
<ul>
<li><ul>
<li><p>案例：</p>
<ul>
<li><ol>
<li>完成重定向</li>
</ol>
</li>
<li><ol>
<li>服务器输出字符数据到浏览器</li>
</ol>
</li>
<li><ol>
<li>服务器输出字节数据到浏览器</li>
</ol>
</li>
<li><ol>
<li><p>验证码</p>
<ul>
<li><ol>
<li>本质：图片</li>
</ol>
</li>
<li><ol>
<li>目的：防止恶意表单注册</li>
</ol>
</li>
<li><p>代码</p>
<ul>
<li>@WebServlet(“/checkCodeServlet”)<br>public class CheckCodeServlet extends HttpServlet {<br>protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>int width = 100;<br>int height = 50;<br>//1.创建一对象，在内存中图片(验证码图片对象)<br>BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
<p>//2.美化图片<br>//2.1 填充背景色<br>Graphics g = image.getGraphics();//画笔对象<br>g.setColor(Color.PINK);//设置画笔颜色<br>g.fillRect(0, 0, width, height); // 从(0,0)开始填充</p>
<p>//2.2画边框<br>g.setColor(Color.BLUE);<br>g.drawRect(0, 0, width - 1, height - 1);</p>
<p>String str = “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789”;<br>//生成随机角标<br>Random ran = new Random();<br>for (int i = 1; i &lt;= 4; i++) {</p>
<pre><code>int index = ran.nextInt(str.length());
//获取字符
char ch = str.charAt(index);//随机字符
//2.3写验证码
g.drawString(ch + &quot;&quot;, width / 5 * i, height / 2);
</code></pre><p>}</p>
<p>//2.4画干扰线<br>g.setColor(Color.GREEN);<br>//随机生成坐标点<br>for (int i = 0; i &lt; 10; i++) {</p>
<pre><code>int x1 = ran.nextInt(width);
int x2 = ran.nextInt(width);
int y1 = ran.nextInt(height);
int y2 = ran.nextInt(height);
g.drawLine(x1, y1, x2, y2);
</code></pre><p>}</p>
<p>//3.将图片输出到页面展示<br>ImageIO.write(image, “jpg”, response.getOutputStream());<br>}</p>
</li>
</ul>
<p>protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>  this.doPost(request, response);<br>}<br>}</p>
</li>
<li><p>Response_案例4_验证码_点击</p>
<ul>
<li><p>分析：</p>
<ul>
<li><p>点击超链接或者图片，需要换一张</p>
<ul>
<li>1.给超链接和图片绑定单击事件</li>
<li>2.重新设置图片的src属性值</li>
</ul>
</li>
</ul>
</li>
<li><p>代码</p>
<ul>
<li>&lt;!DOCTYPE html&gt;<html lang="en">
<head>
<meta charset="UTF-8">
<title>验证码图片</title>
<script>
window.onload = function () {
//1.获取图片对象
var img = document.getElementById("checkCode");
//2.绑定单击事件
img.onclick = function () {
  //加时间戳
  var date = new Date().getTime();
  img.src = "/day15/checkCodeServlet?" + date;
}
}
</script>
</head>
<body>
<img id="checkCode" src="/day15/checkCodeServlet"/>
<a id="change" href="">看不清？换一张！</a>
</body>
</html>

</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="11-ServletContext对象"><a href="#11-ServletContext对象" class="headerlink" title="11 ServletContext对象"></a>11 ServletContext对象</h3><ul>
<li><ol>
<li>概念：代表整个web应用，可以和程序的容器(服务器)来通信。</li>
</ol>
</li>
<li><ol>
<li><p>获取</p>
<ul>
<li><ol>
<li><p>通过request对象获取</p>
<ul>
<li>request.getServletContext();</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>通过HttpServlet获取</p>
<ul>
<li>this.getServletContext();</li>
</ul>
</li>
</ol>
</li>
<li><p>代码</p>
<ul>
<li>@WebServlet(“/servletContextDemo1”)<br>public class ServletContextDemo1 extends HttpServlet {<br>protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>/*<br>  ServletContext对象获取：<pre><code>  1. 通过request对象获取
      request.getServletContext();
  2. 通过HttpServlet获取
      this.getServletContext();
</code></pre>*/<br>//1. 通过request对象获取<br>ServletContext context1 = request.getServletContext();<br>//2. 通过HttpServlet获取<br>ServletContext context2 = this.getServletContext();<br>System.out.println(context1);<br>System.out.println(context2);<br>System.out.println(context1 == context2);//true<br>}<br>protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>this.doPost(request, response);<br>}<br>}</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>功能：</p>
<ul>
<li><ol>
<li><p>获取MIME类型：</p>
<ul>
<li><ul>
<li>MIME类型：在互联网通信过程中定义的一种文件数据类型。</li>
</ul>
<ul>
<li><ul>
<li>格式：大类型/小类型，text/html、image/jpeg</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li>获取：String getMimeType(String file)</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>域对象：共享数据。</p>
<ul>
<li><ol>
<li>setAttribute(String name,Object value)</li>
</ol>
</li>
<li><ol>
<li>getAttribute(String name)</li>
</ol>
</li>
<li><ol>
<li>removeAttribute(String name)</li>
</ol>
<ul>
<li><ul>
<li>ServletContext对象范围：所有用户、所有请求的数据。</li>
</ul>
</li>
</ul>
</li>
<li><p>子主题 4</p>
<ul>
<li>子主题 1</li>
<li>子主题 2</li>
<li>子主题 3</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>获取文件的真实(服务器)路径</p>
<ul>
<li><ol>
<li>方法：</li>
</ol>
<ul>
<li>String getRealPath(String path)  </li>
<li>String b = context.getRealPath(“/b.txt”);//web目录下资源访问</li>
<li>System.out.println(b);</li>
<li>String c = context.getRealPath(“/WEB-INF/c.txt”);//WEB-INF目录下的资源访问</li>
<li>System.out.println(c);</li>
<li>String a = context.getRealPath(“/WEB-INF/classes/a.txt”);//src目录下的资源访问</li>
<li>System.out.println(a);</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
</ul>
<h3 id="12-文件下载"><a href="#12-文件下载" class="headerlink" title="12 文件下载"></a>12 文件下载</h3><ul>
<li><ul>
<li><p>文件下载需求：</p>
<ul>
<li>页面显示超链接</li>
<li>点击超链接后弹出下载提示框</li>
<li>完成图片文件下载</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><p>分析：</p>
<ul>
<li>超链接指向的资源如果能够被浏览器解析，则在浏览器中展示；如果不能解析，则弹出下载提示框。</li>
<li>任何资源都必须弹出下载提示框。</li>
<li>使用响应头设置资源的打开方式：content-disposition:attachment;filename=xxx</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><p>步骤：</p>
<ul>
<li>定义页面，编辑超链接href属性，指向Servlet，传递资源名称filename。</li>
<li>定义Servlet</li>
<li>获取文件名称</li>
<li>使用字节输入流加载文件进内存</li>
<li>指定response的响应头：content-disposition:attachment;filename=xxx</li>
<li>将数据写出到response输出流</li>
</ul>
</li>
</ul>
</li>
<li><p>文件下载_代码实现</p>
<ul>
<li><p>download.html</p>
<ul>
<li>&lt;!DOCTYPE html&gt;<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件下载</title>
</head>
<body>
<a href="/day15/img/1.jpg">图片1</a>
<a href="/day15/img/1.avi">视频</a>
<hr>
<a href="/day15/downloadServlet?filename=九尾.jpg">图片1</a>
<a href="/day15/downloadServlet?filename=1.avi">视频</a>
</body>
</html>
</li>
</ul>
</li>
<li><p>DownloadServlet.java</p>
<ul>
<li><p>@WebServlet(“/downloadServlet”)<br>public class DownloadServlet extends HttpServlet {<br>protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>//1.获取请求参数，文件名称<br>String filename = request.getParameter(“filename”);<br>//2.使用字节输入流加载文件进内存<br>//2.1找到文件服务器路径<br>ServletContext servletContext = this.getServletContext();<br>String realPath = servletContext.getRealPath(“/img/“ + filename);<br>//2.2用字节流关联<br>FileInputStream fis = new FileInputStream(realPath);</p>
<p>//3.设置response的响应头<br>//3.1设置响应头类型：content-type<br>String mimeType = servletContext.getMimeType(filename);//获取文件的mime类型<br>response.setHeader(“content-type”, mimeType);<br>//3.2设置响应头打开方式:content-disposition</p>
<p>//解决中文文件名问题<br>//1.获取user-agent请求头、<br>String agent = request.getHeader(“user-agent”);<br>//2.使用工具类方法编码文件名即可<br>filename = DownLoadUtils.getFileName(agent, filename);</p>
<p>response.setHeader(“content-disposition”, “attachment;filename=” + filename);<br>//4.将输入流的数据写出到输出流中<br>ServletOutputStream sos = response.getOutputStream();<br>byte[] buff = new byte[1024 * 8];<br>int len = 0;<br>while ((len = fis.read(buff)) != -1) {<br>  sos.write(buff, 0, len);<br>}<br>fis.close();<br>}</p>
</li>
</ul>
<p>protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>  this.doPost(request, response);<br>}<br>}</p>
</li>
</ul>
</li>
<li><ul>
<li><p>中文文件问题</p>
<ul>
<li><ul>
<li><p>解决思路：</p>
<ul>
<li><ol>
<li>获取客户端使用的浏览器版本信息</li>
</ol>
</li>
<li><ol>
<li>根据不同的版本信息，设置filename的编码方式不同</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
<li><p>代码</p>
<ul>
<li><p>DownLoadUtils.java</p>
<ul>
<li>public class DownLoadUtils {<br>public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {<br>if (agent.contains(“MSIE”)) {<br>// IE浏览器<br>filename = URLEncoder.encode(filename, “utf-8”);<br>filename = filename.replace(“+”, “ “);<br>} else if (agent.contains(“Firefox”)) {<br>// 火狐浏览器<br>BASE64Encoder base64Encoder = new BASE64Encoder();<br>filename = “=?utf-8?B?” + base64Encoder.encode(filename.getBytes(“utf-8”)) + “?=”;<br>} else {<br>// 其它浏览器<br>filename = URLEncoder.encode(filename, “utf-8”);<br>}<br>return filename;<br>}</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E4%BA%8C%E7%AB%A0Request%E5%92%8CResponse/" data-id="cl403sxr6001hf8vufv4x8cm0" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-Java/第二十一章Servlet和HTTP请求协议" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E4%B8%80%E7%AB%A0Servlet%E5%92%8CHTTP%E8%AF%B7%E6%B1%82%E5%8D%8F%E8%AE%AE/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:35:49.452Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="第二十一章Servlet和HTTP请求协议"><a href="#第二十一章Servlet和HTTP请求协议" class="headerlink" title="第二十一章Servlet和HTTP请求协议"></a>第二十一章Servlet和HTTP请求协议</h2><h3 id="01-Servlet-快速入门"><a href="#01-Servlet-快速入门" class="headerlink" title="01 Servlet_快速入门"></a>01 Servlet_快速入门</h3><ul>
<li><ul>
<li><p>概念：运行在服务器端的小程序。</p>
<ul>
<li><ul>
<li>Servlet就是一个接口，定义了Java类被浏览器访问到(tomcat识别)的规则。</li>
</ul>
</li>
<li><ul>
<li>将来我们自定义一个类，实现Servlet接口，复写方法。</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>快速入门：</p>
<ul>
<li><ol>
<li>创建JavaEE项目</li>
</ol>
</li>
<li><ol>
<li><p>定义一个类，实现Servlet接口</p>
<ul>
<li><ul>
<li>public class ServletDemo1 implements Servlet {}</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li>实现接口中的抽象方法</li>
</ol>
</li>
<li><ol>
<li><p>配置Servlet</p>
<ul>
<li><p>在web.xml中配置：</p>
<ul>
<li><!--配置Servlet -->
<servlet>
<servlet-name>demo1</servlet-name>
<servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class>
</servlet>

</li>
</ul>
</li>
</ul>
<p><servlet-mapping><br>   <servlet-name>demo1&lt;/servlet-name&gt;<br>   <url-pattern>/demo1&lt;/url-pattern&gt;<br>&lt;/servlet-mapping&gt;</p>
</li>
</ol>
</li>
</ul>
</li>
</ul>
<ul>
<li><p>子主题 5</p>
<ul>
<li>子主题 1</li>
<li>子主题 2</li>
<li>子主题 3</li>
<li>子主题 4</li>
<li>子主题 5</li>
<li>子主题 6</li>
<li>子主题 7</li>
</ul>
</li>
<li><p>Servlet_执行原理</p>
<ul>
<li>当服务器接受到客户端浏览器的请求后，会解析请求URL路径，获取访问的Servlet的资源路径。</li>
<li>查找web.xml文件，是否有对应的<url-pattern>标签体内容。</li>
<li>如果有，则在找到对应的<servlet-class>全类名。</li>
<li>tomcat会将字节码文件加载进内存，并且创建其对象。</li>
<li>调用其方法。</li>
</ul>
</li>
</ul>
<h3 id="02-Servlet-生命周期"><a href="#02-Servlet-生命周期" class="headerlink" title="02 Servlet_生命周期"></a>02 Servlet_生命周期</h3><ul>
<li><p>Servlet中的生命周期方法：</p>
<ul>
<li>被创建：执行init方法，只执行一次。</li>
<li>提供服务：执行service方法，执行多次。</li>
<li>被销毁：执行destroy方法，只执行一次。</li>
</ul>
</li>
<li><p>代码</p>
<ul>
<li><p>/**</p>
<ul>
<li>Servlet的方法<br>*/<br>public class ServletDemo2 implements Servlet {</li>
</ul>
<p>/**</p>
<ul>
<li>初始化方法</li>
<li>在Servlet被创建时，执行。只会执行一次<br>*</li>
<li>@param servletConfig</li>
<li>@throws ServletException<br>*/<br>@Override<br>public void init(ServletConfig servletConfig) throws ServletException {<br>System.out.println(“init…”);<br>}</li>
</ul>
<p>/**</p>
<ul>
<li>获取ServletConfig对象</li>
<li>ServletConfig：Servlet的配置对象<br>*</li>
<li>@return<br>*/<br>@Override<br>public ServletConfig getServletConfig() {<br>return null;<br>}</li>
</ul>
<p>/**</p>
<ul>
<li>提供服务方法</li>
<li>每一次Servlet被访问时，执行。执行多次<br>*</li>
<li>@param servletRequest</li>
<li>@param servletResponse</li>
<li>@throws ServletException</li>
<li>@throws IOException<br>*/<br>@Override<br>public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {<br>System.out.println(“service…”);<br>}</li>
</ul>
<p>/**</p>
<ul>
<li>获取Servlet的一些信息，版本、作者等…<br>*</li>
<li>@return<br>*/<br>@Override<br>public String getServletInfo() {<br>return null;<br>}</li>
</ul>
<p>/**</p>
<ul>
<li>销毁方法</li>
<li>在服务器正常关闭时（Servlet销毁），执行，执行一次。<br>*/<br>@Override<br>public void destroy() {<br>System.out.println(“destroy…”);<br>}<br>}</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="Servlet-生命周期详解"><a href="#Servlet-生命周期详解" class="headerlink" title="Servlet_生命周期详解"></a>Servlet_生命周期详解</h3><ul>
<li><ol>
<li><p>被创建：执行init方法，只执行一次。</p>
<ul>
<li><ul>
<li><p>Servlet什么时候被创建？</p>
<ul>
<li><ul>
<li>默认情况下，第一次被访问时，Servlet被创建。</li>
</ul>
</li>
<li><ul>
<li><p>可以配置执行Servlet的创建时机。</p>
<ul>
<li><ul>
<li><p>在<servlet>标签下配置</p>
<ul>
<li><ol>
<li><p>第一次被访问时，创建</p>
<ul>
<li><ul>
<li><load-on-startup>的值为负数</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>在服务器启动时，创建</p>
<ul>
<li><ul>
<li><load-on-startup>的值为0或正整数</li>
</ul>
</li>
<li><ul>
<li>Servlet的init方法，只执行一次，说明一个Servlet在内存中只存在一个对象，Servlet是单例的。</li>
</ul>
</li>
<li><ul>
<li>多个用户同时访问时，可能存在线程安全问题。</li>
</ul>
</li>
<li><ul>
<li>解决：尽量不要在Servlet中定义成员变量。即使定义了成员变量，也不要修改其值（避免并发操作）。</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>提供服务：执行service方法，执行多次。</p>
<ul>
<li><ul>
<li>每次访问Servlet时，Service方法都会被调用一次。</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>被销毁：执行destroy方法，只执行一次。</p>
<ul>
<li><ul>
<li>Servlet被销毁时执行。服务器关闭时，Servlet被销毁。</li>
</ul>
</li>
<li><ul>
<li>只有服务器正常关闭时，才会执行destroy方法。</li>
</ul>
</li>
<li><ul>
<li>destroy方法在Servlet被销毁之前执行，一般用于释放资源。</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><p>&lt;?xml version=”1.0” encoding=”UTF-8”?&gt;</p>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
       version="3.1">

  <!--配置Servlet -->
  <servlet>
      <servlet-name>demo1</servlet-name>
      <servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>demo1</servlet-name>
      <url-pattern>/demo1</url-pattern>
  </servlet-mapping>

  <!--配置Servlet -->
  <servlet>
      <servlet-name>demo2</servlet-name>
      <servlet-class>cn.itcast.web.servlet.ServletDemo2</servlet-class>
      <!--指定Servlet的创建时机
          1.第一次被访问时，创建
              * <load-on-startup>的值为负数（默认值为-1）
          2.在服务器启动时，创建
              * <load-on-startup>的值为0或正整数
      -->
      <load-on-startup>-5</load-on-startup>
  </servlet>

<p>  <servlet-mapping></p>
<pre><code>  &lt;servlet-name&gt;demo2&lt;/servlet-name&gt;
  &lt;url-pattern&gt;/demo2&lt;/url-pattern&gt;
</code></pre><p>  &lt;/servlet-mapping&gt;</p>
</li>
</ul>
<p>&lt;/web-app&gt;</p>
<h3 id="03-Servlet-3-0注解配置"><a href="#03-Servlet-3-0注解配置" class="headerlink" title="03 Servlet_3.0注解配置"></a>03 Servlet_3.0注解配置</h3><ul>
<li><ul>
<li><p>好处：</p>
<ul>
<li><ul>
<li>支持注解配置。可以不需要web.xml了。</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><p>步骤：</p>
<ul>
<li><ol>
<li>创建JavaEE项目，选择Servlet的版本3.0以上，可以不创建web.xml</li>
</ol>
</li>
<li><ol>
<li>定义一个类，实现Servlet接口</li>
</ol>
</li>
<li><ol>
<li>复写方法</li>
</ol>
</li>
<li><ol>
<li>在类上使用@WebServlet注解，进行配置</li>
</ol>
</li>
<li><ul>
<li><p>@WebServlet(“资源路径”)</p>
<ul>
<li>public @interface WebServlet {}<br>按住“Ctrl键”，点击“WebServlet”：</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>@Target({ElementType.TYPE})<br>@Retention(RetentionPolicy.RUNTIME)<br>@Documented<br>public @interface WebServlet {<br>    String name() default “”; // 相当于<Servlet-name></p>
<pre><code>String[] value() default &#123;&#125;; // 代表urlPatterns()属性配置

String[] urlPatterns() default &#123;&#125;; // 相当于&lt;url-pattern&gt;

int loadOnStartup() default -1; // 相当于&lt;load-on-startup&gt;

WebInitParam[] initParams() default &#123;&#125;;

boolean asyncSupported() default false;

String smallIcon() default &quot;&quot;;

String largeIcon() default &quot;&quot;;

String description() default &quot;&quot;;

String displayName() default &quot;&quot;;
</code></pre><p>}<br>Servlet_3.0注解配置方式2</p>
<p>public class ServletDemo implements Servlet {}<br>package cn.itcast.web.servlet;</p>
<p>import javax.servlet.*;<br>import javax.servlet.annotation.WebServlet;<br>import java.io.IOException;</p>
<p>@WebServlet(“/demo2”)<br>public class ServletDemo implements Servlet {<br>    @Override<br>    public void init(ServletConfig servletConfig) throws ServletException {<br>    }</p>
<pre><code>@Override
public ServletConfig getServletConfig() &#123;
    return null;
&#125;

@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException &#123;
    System.out.println(&quot;Servlet3.0来了...&quot;);
&#125;

@Override
public String getServletInfo() &#123;
    return null;
&#125;

@Override
public void destroy() &#123;
&#125;
</code></pre><p>}</p>
<h3 id="04-IDEA与tomcat相关配置"><a href="#04-IDEA与tomcat相关配置" class="headerlink" title="04 IDEA与tomcat相关配置"></a>04 IDEA与tomcat相关配置</h3><ul>
<li><ol>
<li><p>IDEA会为每一个tomcat部署的项目单独建立一份配置文件。</p>
<ul>
<li><ul>
<li>查看控制台的log：Using CATALINA_BASE:   “C:\Users\fqy.IntelliJIdea2018.1\system\tomcat_itcast”</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>工作空间项目和tomcat部署的web项目</p>
<ul>
<li><ul>
<li>tomcat真正访问的是“tomcat部署的web项目”，”tomcat部署的web项目”对应着”工作空间项目”的web目录下的所有资源。</li>
</ul>
</li>
<li><ul>
<li>WEB-INF目录下的资源不能被浏览器直接访问。</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li>断点调试：使用”小虫子”启动（dubug 启动）</li>
</ol>
</li>
</ul>
<h3 id="05-Servlet-体系结构与urlpartten配置"><a href="#05-Servlet-体系结构与urlpartten配置" class="headerlink" title="05 Servlet_体系结构与urlpartten配置"></a>05 Servlet_体系结构与urlpartten配置</h3><ul>
<li><ol>
<li>概念</li>
</ol>
</li>
<li><ol>
<li>步骤</li>
</ol>
</li>
<li><ol>
<li>执行原理</li>
</ol>
</li>
<li><ol>
<li>生命周期</li>
</ol>
</li>
<li><ol>
<li>Servlet3.0 注解配置</li>
</ol>
</li>
<li><ol>
<li><p>Servlet的体系结构    </p>
<ul>
<li>Servlet — 接口</li>
<li>GenericServlet（儿子）— 抽象类</li>
<li>HttpServlet（孙子）— 抽象类</li>
</ul>
</li>
</ol>
</li>
<li><ul>
<li>GenericServlet：将Servlet接口中其他的方法做了默认空实现，只将service()方法作为抽象。</li>
</ul>
</li>
<li><ul>
<li>将来定义Servlet类时，可以继承GenericServlet，实现service()方法即可。</li>
</ul>
</li>
<li><ul>
<li><p>HttpServlet：对http协议的一种封装，简化操作。</p>
<ul>
<li><ol>
<li>定义类继承HttpServlet</li>
</ol>
</li>
<li><ol>
<li>复写doGet/doPost方法</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
<li><p>package cn.itcast.web.servlet;</p>
</li>
</ul>
<p>import javax.jws.WebService;<br>import javax.servlet.*;<br>import javax.servlet.annotation.WebServlet;<br>import java.io.IOException;</p>
<p>@WebServlet(urlPatterns = “/demo1”) // 设置虚拟访问路径<br>public class ServletDemo1 implements Servlet{<br>    @Override<br>    public void init(ServletConfig servletConfig) throws ServletException {<br>    }</p>
<pre><code>@Override
public ServletConfig getServletConfig() &#123;
    return null;
&#125;

@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException &#123;
    System.out.println(&quot;demo1-service...&quot;);
&#125;

@Override
public String getServletInfo() &#123;
    return null;
&#125;

@Override
public void destroy() &#123;

&#125;
</code></pre><p>}<br>public class ServletDemo2 extends GenericServlet {}</p>
<ul>
<li>package cn.itcast.web.servlet;</li>
</ul>
<p>import javax.servlet.GenericServlet;<br>import javax.servlet.ServletException;<br>import javax.servlet.ServletRequest;<br>import javax.servlet.ServletResponse;<br>import javax.servlet.annotation.WebServlet;<br>import java.io.IOException;</p>
<p>@WebServlet(“/demo2”)<br>public class ServletDemo2 extends GenericServlet {<br>    //不需要复写Servlet其它方法，只需要复写service方法<br>    //空实现Servlet其它方法，只写方法生命、不写方法体<br>    @Override<br>    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {<br>        System.out.println(“demo2…”);<br>    }<br>}</p>
<ul>
<li>package cn.itcast.web.servlet;</li>
</ul>
<p>import javax.servlet.ServletException;<br>import javax.servlet.annotation.WebServlet;<br>import javax.servlet.http.HttpServlet;<br>import javax.servlet.http.HttpServletRequest;<br>import javax.servlet.http.HttpServletResponse;<br>import java.io.IOException;</p>
<p>@WebServlet(“/demo3”)<br>public class ServletDemo3 extends HttpServlet {<br>    @Override<br>    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {<br>//        super.doGet(req, resp);<br>        System.out.println(“doGet…”);<br>    }</p>
<pre><code>@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException &#123;
</code></pre><p>//        super.doPost(req, resp);<br>        System.out.println(“doPost…”);<br>    }<br>}</p>
<ul>
<li><p>Servlet_urlpartten配置</p>
<ul>
<li><ol>
<li>概念</li>
</ol>
</li>
<li><ol>
<li>步骤</li>
</ol>
</li>
<li><ol>
<li>执行原理</li>
</ol>
</li>
<li><ol>
<li>生命周期</li>
</ol>
</li>
<li><ol>
<li>Servlet3.0 注解配置</li>
</ol>
</li>
<li><ol>
<li>Servlet的体系结构    </li>
</ol>
</li>
<li><ol>
<li><p>Servlet相关配置</p>
<ul>
<li><ol>
<li><p>urlpartten：Servlet访问路径</p>
<ul>
<li><ol>
<li>一个Servlet可以定义多个访问路径 ： @WebServlet({“/d4”,”/dd4”,”/ddd4”})</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>路径定义规则：</p>
<ul>
<li><ol>
<li>/xxx：路径匹配</li>
</ol>
</li>
<li><ol>
<li>/xxx/xxx:多层路径，目录结构</li>
</ol>
</li>
<li><ol>
<li>*.do：扩展名匹配</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
<h3 id="06-HTTP请求协议"><a href="#06-HTTP请求协议" class="headerlink" title="06 HTTP请求协议"></a>06 HTTP请求协议</h3><ul>
<li><p>HTTP概念：</p>
<ul>
<li>Hyper Text Transfer Protocol 超文本传输协议</li>
</ul>
</li>
<li><ul>
<li>传输协议：定义了客户端和服务器端通信时，发送数据的格式。</li>
</ul>
</li>
<li><ul>
<li><p>特点：</p>
<ul>
<li><ol>
<li>基于TCP/IP的高级协议</li>
</ol>
</li>
<li><ol>
<li>默认端口号:80</li>
</ol>
</li>
<li><ol>
<li>基于请求/响应模型的:一次请求对应一次响应</li>
</ol>
</li>
<li><ol>
<li>无状态的：每次请求之间相互独立，不能交互数据</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><p>历史版本：</p>
<ul>
<li><ul>
<li>1.0：每一次请求响应都会建立新的连接</li>
</ul>
</li>
<li><ul>
<li>1.1：复用连接</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>HTTP请求消息数据格式</p>
<ul>
<li><ol>
<li><p>请求行</p>
<ul>
<li><p>请求方式 请求url 请求协议/版本</p>
<ul>
<li>GET /login.html    HTTP/1.1</li>
</ul>
</li>
<li><ul>
<li><p>请求方式：</p>
<ul>
<li><ul>
<li><p>HTTP协议有7种请求方式，常用的有2种。</p>
<ul>
<li><ul>
<li><p>GET：</p>
<ul>
<li><ol>
<li>请求参数在请求行中，在url后。</li>
</ol>
</li>
<li><ol>
<li>请求的url长度有限制</li>
</ol>
</li>
<li><ol>
<li>不太安全</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><p>POST：</p>
<ul>
<li><ol>
<li>请求参数在请求体中</li>
</ol>
</li>
<li><ol>
<li>请求的url长度没有限制</li>
</ol>
</li>
<li><ol>
<li>相对安全</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>请求头</p>
<ul>
<li>请求头名称: 请求头值</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>请求空行</p>
<ul>
<li>空行</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>请求体(正文)</p>
<ul>
<li><ul>
<li><p>字符串格式：</p>
<ul>
<li>POST /login.html    HTTP/1.1<br>Host: localhost<br>User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0<br>Accept: text/html,application/xhtml+xml,application/xml;q=0.9,<em>/</em>;q=0.8<br>Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2<br>Accept-Encoding: gzip, deflate<br>Referer: <a target="_blank" rel="noopener" href="http://localhost/login.html">http://localhost/login.html</a><br>Connection: keep-alive<br>Upgrade-Insecure-Requests: 1</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>username=zhangsan</p>
</li>
</ol>
</li>
</ul>
</li>
</ul>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E4%B8%80%E7%AB%A0Servlet%E5%92%8CHTTP%E8%AF%B7%E6%B1%82%E5%8D%8F%E8%AE%AE/" data-id="cl403sxr5001ef8vu3k22g5or" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-Java/第二十章Tomcat" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E7%AB%A0Tomcat/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:35:42.302Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="第二十章Tomcat"><a href="#第二十章Tomcat" class="headerlink" title="第二十章Tomcat"></a>第二十章Tomcat</h2><h3 id="01-Web相关概念"><a href="#01-Web相关概念" class="headerlink" title="01 Web相关概念"></a>01 Web相关概念</h3><ul>
<li><ol>
<li><p>软件架构</p>
<ul>
<li><ol>
<li>C/S：客户端/服务器端</li>
</ol>
</li>
<li><ol>
<li>B/S：浏览器/服务器端</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>资源分类</p>
<ul>
<li><ol>
<li><p>静态资源：所有用户访问后，得到的结果都是一样的，称为静态资源。静态资源可以直接被浏览器解析。</p>
<ul>
<li><ul>
<li>如： Html、Css、JavaScript</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>动态资源:每个用户访问相同资源后，得到的结果可能不一样，称为动态资源。动态资源被访问后，需要先转换为静态资源，再返回给浏览器。</p>
<ul>
<li><ul>
<li>如：servlet/jsp、php、asp …</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>网络通信三要素</p>
<ul>
<li><ol>
<li>IP：电子设备(计算机)在网络中的唯一标识。</li>
</ol>
</li>
<li><ol>
<li>端口：应用程序在计算机中的唯一标识，端口号取值范围：0~65536。</li>
</ol>
</li>
<li><ol>
<li><p>传输协议：规定了数据传输的规则。</p>
<ul>
<li><ol>
<li>基础协议：</li>
</ol>
<ul>
<li><ol>
<li>tcp：安全协议，三次握手，速度稍慢。</li>
</ol>
</li>
<li><ol>
<li>udp：不安全协议，速度快。</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
<li><p>web服务器软件</p>
<ul>
<li><ul>
<li>服务器：安装了服务器软件的计算机</li>
</ul>
</li>
<li><ul>
<li><p>服务器软件：接收用户的请求、处理请求、做出响应。</p>
<ul>
<li><ul>
<li>web服务器软件：接收用户的请求、处理请求、做出响应。</li>
</ul>
</li>
<li><ul>
<li>在web服务器软件中，可以部署web项目，让用户通过浏览器来访问这些项目。</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li>web容器</li>
</ul>
</li>
<li><ul>
<li><p>常见的java相关的web服务器软件：</p>
<ul>
<li><ul>
<li>webLogic：oracle公司，大型的JavaEE服务器，支持所有的JavaEE规范，收费的。</li>
</ul>
</li>
<li><ul>
<li>webSphere：IBM公司，大型的JavaEE服务器，支持所有的JavaEE规范，收费的。</li>
</ul>
</li>
<li><ul>
<li>JBOSS：JBOSS公司，大型的JavaEE服务器，支持所有的JavaEE规范，收费的。</li>
</ul>
</li>
<li><ul>
<li>Tomcat：Apache基金组织，中小型的JavaEE服务器，仅仅支持少量的JavaEE规范servlet/jsp。开源的，免费的。</li>
</ul>
</li>
<li><ul>
<li>JavaEE：Java语言在企业级开发中使用的技术规范的总和，一共规定了13项大的规范。</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="02-Tomcat基本操作-web服务器软件"><a href="#02-Tomcat基本操作-web服务器软件" class="headerlink" title="02 Tomcat基本操作(web服务器软件)"></a>02 Tomcat基本操作(web服务器软件)</h3><ul>
<li><ol>
<li>下载：<a target="_blank" rel="noopener" href="http://tomcat.apache.org/">http://tomcat.apache.org/</a></li>
</ol>
</li>
<li><ol>
<li><p>安装：解压压缩包即可。</p>
<ul>
<li><ul>
<li>注意：安装目录建议不要有中文和空格。</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li>卸载：删除目录就行了。</li>
</ol>
</li>
<li><ol>
<li><p>启动：</p>
<ul>
<li><ul>
<li>bin/startup.bat ,双击运行该文件即可</li>
</ul>
</li>
<li><ul>
<li><p>访问：浏览器输入：</p>
<ul>
<li><a href="http://localhost:8080（访问自己）">http://localhost:8080（访问自己）</a></li>
<li><a href="http://别人的ip:8080（访问别人）">http://别人的ip:8080（访问别人）</a></li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><p>可能遇到的问题：</p>
<ul>
<li><ol>
<li><p>黑窗口一闪而过：</p>
<ul>
<li><ul>
<li>原因： 没有正确配置JAVA_HOME环境变量</li>
</ul>
</li>
<li><ul>
<li>解决方案：正确配置JAVA_HOME环境变量</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>启动报错：</p>
<ul>
<li><ol>
<li>暴力：找到占用的端口号，并且找到对应的进程，杀死该进程。</li>
</ol>
<ul>
<li><ul>
<li>netstat -ano</li>
</ul>
</li>
</ul>
</li>
<li><ol>
<li>温柔：修改自身的端口号。</li>
</ol>
<ul>
<li><ul>
<li>conf/server.xml</li>
</ul>
</li>
<li><ul>
<li><Connector port="8888" protocol="HTTP/1.1"

- connectionTimeout="20000"
- redirectPort="8445" />
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li>一般会将tomcat的默认端口号修改为80。80端口号是http协议的默认端口号。</li>
</ul>
</li>
<li><ul>
<li>好处：在访问时，不用输入端口号</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>关闭</p>
<ul>
<li><ol>
<li><p>正常关闭：</p>
<ul>
<li><ul>
<li>bin/shutdown.bat</li>
</ul>
</li>
<li><ul>
<li>ctrl+c</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>强制关闭：</p>
<ul>
<li><ul>
<li>点击启动窗口的×</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>配置</p>
<ul>
<li><ul>
<li><p>部署项目的方式：</p>
<ul>
<li><ol>
<li><p>直接将项目放到webapps目录下即可。</p>
<ul>
<li><ul>
<li>/hello：项目的访问路径—&gt;虚拟目录</li>
</ul>
</li>
<li><ul>
<li>简化部署：将项目打成一个war包，再将war包放置到webapps目录下。</li>
</ul>
</li>
<li><ul>
<li>war包会自动解压缩</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>配置conf/server.xml文件</p>
<ul>
<li>在<Host>标签体中配置</li>
<li><Context docBase="D:\hello" path="/hehe" /></li>
<li><ul>
<li>docBase:项目存放的路径</li>
</ul>
</li>
<li><ul>
<li>path：虚拟目录</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>在conf\Catalina\localhost创建任意名称的xml文件。在文件中编写：</p>
<ul>
<li><Context docBase="D:\hello" /></li>
<li><ul>
<li>虚拟目录：xml文件的名称</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><p>项目形式2种，静态项目和动态项目：</p>
<ul>
<li><ul>
<li>静态项目：存放静态资源，html、css、js，图片\文本\视频…</li>
</ul>
</li>
<li><ul>
<li><p>动态项目：静态资源+动态资源(servlet\jsp…)</p>
<ul>
<li><ul>
<li><p>目录结构</p>
<ul>
<li><ul>
<li><p>java动态项目的目录结构：</p>
<ul>
<li><p>— 项目的根目录</p>
<ul>
<li><p>— WEB-INF目录：</p>
<ul>
<li>— web.xml：web项目的核心配置文件</li>
<li>— classes目录：放置字节码文件的目录</li>
<li>— lib目录：放置依赖的jar包</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><p>Tomcat 目录结构</p>
</li>
<li><p>Tomcat 启动</p>
<ul>
<li>本机:tomcat默认端口号 —— <a target="_blank" rel="noopener" href="http://127.0.0.1:8080/">http://127.0.0.1:8080/</a>   <a target="_blank" rel="noopener" href="http://localhost:8080/">http://localhost:8080/</a></li>
<li>使用电脑ip地址，访问tomcat。</li>
</ul>
</li>
<li><p>tomcat_启动问题分析</p>
</li>
</ul>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E7%AB%A0Tomcat/" data-id="cl403sxr9001mf8vuaf75boew" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  


  <nav id="page-nav">
    
    <a class="extend prev" rel="prev" href="/notes-on-computer-expertise/page/7/">&laquo; Prev</a><a class="page-number" href="/notes-on-computer-expertise/">1</a><span class="space">&hellip;</span><a class="page-number" href="/notes-on-computer-expertise/page/6/">6</a><a class="page-number" href="/notes-on-computer-expertise/page/7/">7</a><span class="page-number current">8</span><a class="page-number" href="/notes-on-computer-expertise/page/9/">9</a><a class="page-number" href="/notes-on-computer-expertise/page/10/">10</a><span class="space">&hellip;</span><a class="page-number" href="/notes-on-computer-expertise/page/14/">14</a><a class="extend next" rel="next" href="/notes-on-computer-expertise/page/9/">Next &raquo;</a>
  </nav>

</section>
        
          <aside id="sidebar">
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Categories</h3>
    <div class="widget">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/C-%E5%B7%A5%E5%85%B7/">C#工具</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/C-%E5%B7%A5%E5%85%B7/">C++工具</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/Mysql/">Mysql</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/blender/">blender</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/linux/">linux</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/manim/">manim</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/spring/">spring</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/vba%E5%9F%BA%E7%A1%80%E6%93%8D%E4%BD%9C/">vba基础操作</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E5%88%9B%E9%80%A0%E6%A8%A1%E5%BC%8F/">创造模式</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/">操作系统</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/">操作系统基础知识</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91/">操作系统开发</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%95%B0%E5%AD%A6/">数学</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/">数据结构</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/">数据结构基础知识</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%A8%A1%E6%9D%BF/">模板</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/">深度学习</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E8%8B%B1%E8%AF%AD/">英语</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E8%99%9A%E5%B9%BB4/">虚幻4</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E5%8E%9F%E7%90%86/">计算机组成原理</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/">计算机网络</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tags</h3>
    <div class="widget">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/notes-on-computer-expertise/tags/C/" rel="tag">C++</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget tagcloud">
      <a href="/notes-on-computer-expertise/tags/C/" style="font-size: 10px;">C++</a>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2022/05/">May 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2022/03/">March 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2022/02/">February 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2022/01/">January 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2021/12/">December 2021</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/31/vue/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6%E9%AA%8C%E8%AF%81%E7%A0%81%E6%97%A0%E6%B3%95%E6%98%BE%E7%A4%BA/">(no title)</a>
          </li>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/26/%E6%95%B0%E6%8D%AE%E5%BA%93/navicat%E5%AE%89%E8%A3%85/">(no title)</a>
          </li>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/25/%E8%99%9A%E5%B9%BB4%E5%BC%95%E6%93%8E%E5%BC%80%E5%8F%91/%E8%99%9A%E5%B9%BB%E5%9B%9B%20mod%E5%88%B6%E4%BD%9C/">(no title)</a>
          </li>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/23/python/python%E6%89%B9%E9%87%8F%E7%94%9F%E6%88%90%E6%95%B0%E6%8D%AE/">(no title)</a>
          </li>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/23/vba%E5%9F%BA%E7%A1%80%E6%93%8D%E4%BD%9C%E7%AC%94%E8%AE%B0/EXCEL%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/">(no title)</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      
      &copy; 2022 John Doe<br>
      Powered by <a href="https://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>

    </div>
    <nav id="mobile-nav">
  
    <a href="/notes-on-computer-expertise/" class="mobile-nav-link">Home</a>
  
    <a href="/notes-on-computer-expertise/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    


<script src="/notes-on-computer-expertise/js/jquery-3.4.1.min.js"></script>



  
<script src="/notes-on-computer-expertise/fancybox/jquery.fancybox.min.js"></script>




<script src="/notes-on-computer-expertise/js/script.js"></script>





  </div>
<script type="text/x-mathjax-config">
    MathJax.Hub.Config({
        tex2jax: {
            inlineMath: [ ["$","$"], ["\\(","\\)"] ],
            skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code'],
            processEscapes: true
        }
    });
    MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax();
        for (var i = 0; i < all.length; ++i)
            all[i].SourceElement().parentNode.className += ' has-jax';
    });
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML"></script>
</body>
</html>